AwContents.java revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)package org.chromium.android_webview; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)import android.app.Activity; 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.ComponentCallbacks2; 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Context; 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.res.Configuration; 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.graphics.Bitmap; 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport android.graphics.Canvas; 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.graphics.Color; 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.graphics.Picture; 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.graphics.Rect; 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.net.http.SslCertificate; 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.AsyncTask; 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Build; 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Bundle; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Message; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.text.TextUtils; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.util.Log; 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.view.KeyEvent; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.MotionEvent; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.View; 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import android.view.ViewGroup; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.accessibility.AccessibilityEvent; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.accessibility.AccessibilityNodeInfo; 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.accessibility.AccessibilityNodeProvider; 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.inputmethod.EditorInfo; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.inputmethod.InputConnection; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.webkit.GeolocationPermissions; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.webkit.ValueCallback; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.widget.OverScroller; 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.base.CalledByNative; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.base.JNINamespace; 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport org.chromium.base.ThreadUtils; 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport org.chromium.components.navigation_interception.InterceptNavigationDelegate; 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport org.chromium.components.navigation_interception.NavigationParams; 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.content.browser.ContentSettings; 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.content.browser.ContentViewClient; 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.content.browser.ContentViewCore; 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.content.browser.ContentViewStatics; 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)import org.chromium.content.browser.LoadUrlParams; 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.content.browser.NavigationHistory; 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.content.browser.PageTransitionTypes; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.content.common.CleanupReference; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.content_public.browser.GestureStateListener; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.ui.base.ActivityWindowAndroid; 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import org.chromium.ui.base.WindowAndroid; 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport org.chromium.ui.gfx.DeviceDisplayInfo; 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport java.io.File; 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import java.lang.annotation.Annotation; 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import java.net.MalformedURLException; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import java.net.URL; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import java.util.ArrayList; 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)import java.util.HashMap; 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport java.util.List; 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)import java.util.concurrent.Callable; 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/** 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Exposes the native AwContents class, and together these classes wrap the ContentViewCore 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * and Browser components that are required to implement Android WebView API. This is the 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * primary entry point for the WebViewProvider implementation; it holds a 1:1 object 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * relationship with application WebView instances. 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * (We define this class independent of the hidden WebViewProvider interfaces, to allow 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * continuous build & test in the open source SDK-based tree). 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)@JNINamespace("android_webview") 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public class AwContents { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private static final String TAG = "AwContents"; 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final String WEB_ARCHIVE_EXTENSION = ".mht"; 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Used to avoid enabling zooming in / out if resulting zooming will 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // produce little visible difference. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final float ZOOM_CONTROLS_EPSILON = 0.007f; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * WebKit hit test related data strcutre. These are used to implement 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * getHitTestResult, requestFocusNodeHref, requestImageRef methods in WebView. 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * All values should be updated together. The native counterpart is 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * AwHitTestData. 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public static class HitTestData { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Used in getHitTestResult. 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public int hitTestResultType; 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public String hitTestResultExtraData; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Used in requestFocusNodeHref (all three) and requestImageRef (only imgSrc). 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public String href; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public String anchorText; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public String imgSrc; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Interface that consumers of {@link AwContents} must implement to allow the proper 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * dispatching of view methods through the containing view. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public interface InternalAccessDelegate extends ContentViewCore.InternalAccessDelegate { 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @see View#overScrollBy(int, int, int, int, int, int, int, int, boolean); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void overScrollBy(int deltaX, int deltaY, 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int scrollX, int scrollY, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int scrollRangeX, int scrollRangeY, 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int maxOverScrollX, int maxOverScrollY, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) boolean isTouchEvent); 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /** 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @see View#scrollTo(int, int) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void super_scrollTo(int scrollX, int scrollY); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /** 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @see View#setMeasuredDimension(int, int) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void setMeasuredDimension(int measuredWidth, int measuredHeight); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @see View#getScrollBarStyle() 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int super_getScrollBarStyle(); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Requests a callback on the native DrawGL method (see getAwDrawGLFunction) 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch * if called from within onDraw, |canvas| will be non-null and hardware accelerated. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * otherwise, |canvas| will be null, and the container view itself will be hardware 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * accelerated. 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @return false indicates the GL draw request was not accepted, and the caller 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * should fallback to the SW path. 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */ 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) boolean requestDrawGL(Canvas canvas); 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private long mNativeAwContents; 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final AwBrowserContext mBrowserContext; 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final ViewGroup mContainerView; 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private ContentViewCore mContentViewCore; 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final AwContentsClient mContentsClient; 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final AwContentViewClient mContentViewClient; 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final AwContentsClientBridge mContentsClientBridge; 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final AwWebContentsDelegate mWebContentsDelegate; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwContentsIoThreadClient mIoThreadClient; 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final InternalAccessDelegate mInternalAccessAdapter; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwLayoutSizer mLayoutSizer; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwZoomControls mZoomControls; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwScrollOffsetManager mScrollOffsetManager; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private OverScrollGlow mOverScrollGlow; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This can be accessed on any thread after construction. See AwContentsIoThreadClient. 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwSettings mSettings; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final ScrollAccessibilityHelper mScrollAccessibilityHelper; 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private boolean mIsPaused; 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private boolean mIsViewVisible; 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private boolean mIsWindowVisible; 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private boolean mIsAttachedToWindow; 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private Bitmap mFavicon; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private boolean mHasRequestedVisitedHistoryFromClient; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(boliu): This should be in a global context, not per webview. 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private final double mDIPScale; 16923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The base background color, i.e. not accounting for any CSS body from the current page. 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private int mBaseBackgroundColor = Color.WHITE; 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Must call nativeUpdateLastHitTestData first to update this before use. 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private final HitTestData mPossiblyStaleHitTestData = new HitTestData(); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private final DefaultVideoPosterRequestHandler mDefaultVideoPosterRequestHandler; 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Bound method for suppling Picture instances to the AwContentsClient. Will be null if the 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // picture listener API has not yet been enabled, or if it is using invalidation-only mode. 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private Callable<Picture> mPictureListenerContentProvider; 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private boolean mContainerViewFocused; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private boolean mWindowFocused; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // These come from the compositor and are updated synchronously (in contrast to the values in 18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // ContentViewCore, which are updated at end of every frame). 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private float mPageScaleFactor = 1.0f; 188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private float mMinPageScaleFactor = 1.0f; 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private float mMaxPageScaleFactor = 1.0f; 19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private float mContentWidthDip; 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private float mContentHeightDip; 1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private AwAutofillManagerDelegate mAwAutofillManagerDelegate; 194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private ComponentCallbacks2 mComponentCallbacks; 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private AwPdfExporter mAwPdfExporter; 198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This flag indicates that ShouldOverrideUrlNavigation should be posted 200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // through the resourcethrottle. This is only used for popup windows. 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private boolean mDeferredShouldOverrideUrlLoadingIsPendingForPopup; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static final class DestroyRunnable implements Runnable { 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private final long mNativeAwContents; 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private DestroyRunnable(long nativeAwContents) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mNativeAwContents = nativeAwContents; 20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void run() { 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is a no-op if not currently attached. 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nativeOnDetachedFromWindow(mNativeAwContents); 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nativeDestroy(mNativeAwContents); 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Reference to the active mNativeAwContents pointer while it is active use 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // (ie before it is destroyed). 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private CleanupReference mCleanupReference; 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // A list of references to native pointers where the Java counterpart has been 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // destroyed, but are held here because they are waiting for onDetachFromWindow 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // to release GL resources. This is cleared inside onDetachFromWindow. 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private List<CleanupReference> mPendingDetachCleanupReferences; 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) //-------------------------------------------------------------------------------------------- 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private class IoThreadClientImpl implements AwContentsIoThreadClient { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // All methods are called on the IO thread. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public int getCacheMode() { 2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return mSettings.getCacheMode(); 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public InterceptedRequestData shouldInterceptRequest(final String url, 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) boolean isMainFrame) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InterceptedRequestData interceptedRequestData; 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Return the response directly if the url is default video poster url. 23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) interceptedRequestData = mDefaultVideoPosterRequestHandler.shouldInterceptRequest(url); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (interceptedRequestData != null) return interceptedRequestData; 24123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interceptedRequestData = mContentsClient.shouldInterceptRequest(url); 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (interceptedRequestData == null) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.getCallbackHelper().postOnLoadResource(url); 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (isMainFrame && interceptedRequestData != null && 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) interceptedRequestData.getData() == null) { 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In this case the intercepted URLRequest job will simulate an empty response 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // which doesn't trigger the onReceivedError callback. For WebViewClassic 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // compatibility we synthesize that callback. http://crbug.com/180950 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.getCallbackHelper().postOnReceivedError( 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ErrorCodeConversionHelper.ERROR_UNKNOWN, 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) null /* filled in by the glue layer */, url); 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return interceptedRequestData; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public boolean shouldBlockContentUrls() { 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !mSettings.getAllowContentAccess(); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public boolean shouldBlockFileUrls() { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !mSettings.getAllowFileAccess(); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public boolean shouldBlockNetworkLoads() { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return mSettings.getBlockNetworkLoads(); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public void onDownloadStart(String url, 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String userAgent, 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String contentDisposition, 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String mimeType, 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) long contentLength) { 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.getCallbackHelper().postOnDownloadStart(url, userAgent, 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contentDisposition, mimeType, contentLength); 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @Override 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void newLoginRequest(String realm, String account, String args) { 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.getCallbackHelper().postOnReceivedLoginRequest(realm, account, args); 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //-------------------------------------------------------------------------------------------- 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When the navigation is for a newly created WebView (i.e. a popup), intercept the navigation 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // here for implementing shouldOverrideUrlLoading. This is to send the shouldOverrideUrlLoading 294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // callback to the correct WebViewClient that is associated with the WebView. 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, use this delegate only to post onPageStarted messages. 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We are not using WebContentsObserver.didStartLoading because of stale URLs, out of order 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // onPageStarted's and double onPageStarted's. 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public boolean shouldIgnoreNavigation(NavigationParams navigationParams) { 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) final String url = navigationParams.url; 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) boolean ignoreNavigation = false; 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mDeferredShouldOverrideUrlLoadingIsPendingForPopup) { 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mDeferredShouldOverrideUrlLoadingIsPendingForPopup = false; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If this is used for all navigations in future, cases for application initiated 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // load, redirect and backforward should also be filtered out. 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!navigationParams.isPost) { 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ignoreNavigation = mContentsClient.shouldOverrideUrlLoading(url); 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The shouldOverrideUrlLoading call might have resulted in posting messages to the 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // UI thread. Using sendMessage here (instead of calling onPageStarted directly) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // will allow those to run in order. 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ignoreNavigation) { 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.getCallbackHelper().postOnPageStarted(url); 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ignoreNavigation; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) //-------------------------------------------------------------------------------------------- 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private class AwLayoutSizerDelegate implements AwLayoutSizer.Delegate { 32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public void requestLayout() { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContainerView.requestLayout(); 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void setMeasuredDimension(int measuredWidth, int measuredHeight) { 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mInternalAccessAdapter.setMeasuredDimension(measuredWidth, measuredHeight); 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void setFixedLayoutSize(int widthDip, int heightDip) { 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mNativeAwContents == 0) return; 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nativeSetFixedLayoutSize(mNativeAwContents, widthDip, heightDip); 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @Override 34223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public boolean isLayoutParamsHeightWrapContent() { 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return mContainerView.getLayoutParams() != null && 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mContainerView.getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT; 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) //-------------------------------------------------------------------------------------------- 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private class AwScrollOffsetManagerDelegate implements AwScrollOffsetManager.Delegate { 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @Override 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void overScrollContainerViewBy(int deltaX, int deltaY, int scrollX, int scrollY, 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int scrollRangeX, int scrollRangeY, boolean isTouchEvent) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mInternalAccessAdapter.overScrollBy(deltaX, deltaY, scrollX, scrollY, 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scrollRangeX, scrollRangeY, 0, 0, isTouchEvent); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) @Override 358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public void scrollContainerViewTo(int x, int y) { 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mInternalAccessAdapter.super_scrollTo(x, y); 36023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 36223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) @Override 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void scrollNativeTo(int x, int y) { 36423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (mNativeAwContents == 0) return; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nativeScrollTo(mNativeAwContents, x, y); 36623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) @Override 3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public int getContainerViewScrollX() { 370 return mContainerView.getScrollX(); 371 } 372 373 @Override 374 public int getContainerViewScrollY() { 375 return mContainerView.getScrollY(); 376 } 377 378 @Override 379 public void invalidate() { 380 mContainerView.invalidate(); 381 } 382 } 383 384 //-------------------------------------------------------------------------------------------- 385 private class AwGestureStateListener extends GestureStateListener { 386 @Override 387 public void onPinchStarted() { 388 // While it's possible to re-layout the view during a pinch gesture, the effect is very 389 // janky (especially that the page scale update notification comes from the renderer 390 // main thread, not from the impl thread, so it's usually out of sync with what's on 391 // screen). It's also quite expensive to do a re-layout, so we simply postpone 392 // re-layout for the duration of the gesture. This is compatible with what 393 // WebViewClassic does. 394 mLayoutSizer.freezeLayoutRequests(); 395 } 396 397 @Override 398 public void onPinchEnded() { 399 mLayoutSizer.unfreezeLayoutRequests(); 400 } 401 402 @Override 403 public void onFlingCancelGesture() { 404 mScrollOffsetManager.onFlingCancelGesture(); 405 } 406 407 @Override 408 public void onUnhandledFlingStartEvent(int velocityX, int velocityY) { 409 mScrollOffsetManager.onUnhandledFlingStartEvent(velocityX, velocityY); 410 } 411 412 @Override 413 public void onScrollUpdateGestureConsumed() { 414 mScrollAccessibilityHelper.postViewScrolledAccessibilityEventCallback(); 415 } 416 } 417 418 //-------------------------------------------------------------------------------------------- 419 private class AwComponentCallbacks implements ComponentCallbacks2 { 420 @Override 421 public void onTrimMemory(int level) { 422 if (mNativeAwContents == 0) return; 423 nativeTrimMemory(mNativeAwContents, level); 424 } 425 426 @Override 427 public void onLowMemory() {} 428 429 @Override 430 public void onConfigurationChanged(Configuration configuration) {} 431 }; 432 433 //-------------------------------------------------------------------------------------------- 434 private class AwLayoutChangeListener implements View.OnLayoutChangeListener { 435 @Override 436 public void onLayoutChange(View v, int left, int top, int right, int bottom, 437 int oldLeft, int oldTop, int oldRight, int oldBottom) { 438 assert v == mContainerView; 439 mLayoutSizer.onLayoutChange(); 440 } 441 } 442 443 /** 444 * @param browserContext the browsing context to associate this view contents with. 445 * @param containerView the view-hierarchy item this object will be bound to. 446 * @param internalAccessAdapter to access private methods on containerView. 447 * @param contentsClient will receive API callbacks from this WebView Contents. 448 * @param awSettings AwSettings instance used to configure the AwContents. 449 * 450 * This constructor uses the default view sizing policy. 451 */ 452 public AwContents(AwBrowserContext browserContext, ViewGroup containerView, 453 InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient, 454 AwSettings awSettings) { 455 this(browserContext, containerView, internalAccessAdapter, contentsClient, awSettings, 456 new AwLayoutSizer()); 457 } 458 459 /** 460 * @param layoutSizer the AwLayoutSizer instance implementing the sizing policy for the view. 461 * 462 * This version of the constructor is used in test code to inject test versions of the above 463 * documented classes. 464 */ 465 public AwContents(AwBrowserContext browserContext, ViewGroup containerView, 466 InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient, 467 AwSettings settings, AwLayoutSizer layoutSizer) { 468 mBrowserContext = browserContext; 469 mContainerView = containerView; 470 mInternalAccessAdapter = internalAccessAdapter; 471 mContentsClient = contentsClient; 472 mContentViewClient = new AwContentViewClient(contentsClient, settings); 473 mLayoutSizer = layoutSizer; 474 mSettings = settings; 475 mDIPScale = DeviceDisplayInfo.create(mContainerView.getContext()).getDIPScale(); 476 mLayoutSizer.setDelegate(new AwLayoutSizerDelegate()); 477 mLayoutSizer.setDIPScale(mDIPScale); 478 mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient, mContainerView); 479 mContentsClientBridge = new AwContentsClientBridge(contentsClient); 480 mZoomControls = new AwZoomControls(this); 481 mIoThreadClient = new IoThreadClientImpl(); 482 mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl(); 483 484 AwSettings.ZoomSupportChangeListener zoomListener = 485 new AwSettings.ZoomSupportChangeListener() { 486 @Override 487 public void onGestureZoomSupportChanged( 488 boolean supportsDoubleTapZoom, boolean supportsMultiTouchZoom) { 489 mContentViewCore.updateDoubleTapSupport(supportsDoubleTapZoom); 490 mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoom); 491 } 492 493 }; 494 mSettings.setZoomListener(zoomListener); 495 mDefaultVideoPosterRequestHandler = new DefaultVideoPosterRequestHandler(mContentsClient); 496 mSettings.setDefaultVideoPosterURL( 497 mDefaultVideoPosterRequestHandler.getDefaultVideoPosterURL()); 498 mSettings.setDIPScale(mDIPScale); 499 mScrollOffsetManager = new AwScrollOffsetManager(new AwScrollOffsetManagerDelegate(), 500 new OverScroller(mContainerView.getContext())); 501 mScrollAccessibilityHelper = new ScrollAccessibilityHelper(mContainerView); 502 503 setOverScrollMode(mContainerView.getOverScrollMode()); 504 setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle()); 505 mContainerView.addOnLayoutChangeListener(new AwLayoutChangeListener()); 506 507 setNewAwContents(nativeInit(mBrowserContext)); 508 509 onVisibilityChanged(mContainerView, mContainerView.getVisibility()); 510 onWindowVisibilityChanged(mContainerView.getWindowVisibility()); 511 } 512 513 private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView, 514 InternalAccessDelegate internalDispatcher, int nativeWebContents, 515 GestureStateListener gestureStateListener, 516 ContentViewClient contentViewClient, 517 ContentViewCore.ZoomControlsDelegate zoomControlsDelegate) { 518 Context context = containerView.getContext(); 519 ContentViewCore contentViewCore = new ContentViewCore(context); 520 contentViewCore.initialize(containerView, internalDispatcher, nativeWebContents, 521 context instanceof Activity ? 522 new ActivityWindowAndroid((Activity) context) : 523 new WindowAndroid(context.getApplicationContext())); 524 contentViewCore.addGestureStateListener(gestureStateListener); 525 contentViewCore.setContentViewClient(contentViewClient); 526 contentViewCore.setZoomControlsDelegate(zoomControlsDelegate); 527 return contentViewCore; 528 } 529 530 /** 531 * Common initialization routine for adopting a native AwContents instance into this 532 * java instance. 533 * 534 * TAKE CARE! This method can get called multiple times per java instance. Code accordingly. 535 * ^^^^^^^^^ See the native class declaration for more details on relative object lifetimes. 536 */ 537 private void setNewAwContents(long newAwContentsPtr) { 538 if (mNativeAwContents != 0) { 539 destroy(); 540 mContentViewCore = null; 541 } 542 543 assert mNativeAwContents == 0 && mCleanupReference == null && mContentViewCore == null; 544 545 mNativeAwContents = newAwContentsPtr; 546 // TODO(joth): when the native and java counterparts of AwBrowserContext are hooked up to 547 // each other, we should update |mBrowserContext| according to the newly received native 548 // WebContent's browser context. 549 550 // The native side object has been bound to this java instance, so now is the time to 551 // bind all the native->java relationships. 552 mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents)); 553 554 int nativeWebContents = nativeGetWebContents(mNativeAwContents); 555 mContentViewCore = createAndInitializeContentViewCore( 556 mContainerView, mInternalAccessAdapter, nativeWebContents, 557 new AwGestureStateListener(), mContentViewClient, mZoomControls); 558 nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge, 559 mIoThreadClient, mInterceptNavigationDelegate); 560 mContentsClient.installWebContentsObserver(mContentViewCore); 561 mSettings.setWebContents(nativeWebContents); 562 nativeSetDipScale(mNativeAwContents, (float) mDIPScale); 563 updateGlobalVisibleRect(); 564 565 // The only call to onShow. onHide should never be called. 566 mContentViewCore.onShow(); 567 } 568 569 /** 570 * Called on the "source" AwContents that is opening the popup window to 571 * provide the AwContents to host the pop up content. 572 */ 573 public void supplyContentsForPopup(AwContents newContents) { 574 int popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents); 575 if (popupNativeAwContents == 0) { 576 Log.w(TAG, "Popup WebView bind failed: no pending content."); 577 if (newContents != null) newContents.destroy(); 578 return; 579 } 580 if (newContents == null) { 581 nativeDestroy(popupNativeAwContents); 582 return; 583 } 584 585 newContents.receivePopupContents(popupNativeAwContents); 586 } 587 588 // Recap: supplyContentsForPopup() is called on the parent window's content, this method is 589 // called on the popup window's content. 590 private void receivePopupContents(int popupNativeAwContents) { 591 mDeferredShouldOverrideUrlLoadingIsPendingForPopup = true; 592 // Save existing view state. 593 final boolean wasAttached = mIsAttachedToWindow; 594 final boolean wasViewVisible = mIsViewVisible; 595 final boolean wasWindowVisible = mIsWindowVisible; 596 final boolean wasPaused = mIsPaused; 597 final boolean wasFocused = mContainerViewFocused; 598 final boolean wasWindowFocused = mWindowFocused; 599 600 // Properly clean up existing mContentViewCore and mNativeAwContents. 601 if (wasFocused) onFocusChanged(false, 0, null); 602 if (wasWindowFocused) onWindowFocusChanged(false); 603 if (wasViewVisible) setViewVisibilityInternal(false); 604 if (wasWindowVisible) setWindowVisibilityInternal(false); 605 if (!wasPaused) onPause(); 606 // Not calling onDetachedFromWindow here because native code requires GL context to release 607 // GL resources. This case is properly handled when destroy is called while still attached 608 // to window. 609 610 setNewAwContents(popupNativeAwContents); 611 612 // Finally refresh all view state for mContentViewCore and mNativeAwContents. 613 if (!wasPaused) onResume(); 614 if (wasAttached) onAttachedToWindow(); 615 onSizeChanged(mContainerView.getWidth(), mContainerView.getHeight(), 0, 0); 616 if (wasWindowVisible) setWindowVisibilityInternal(true); 617 if (wasViewVisible) setViewVisibilityInternal(true); 618 if (wasWindowFocused) onWindowFocusChanged(wasWindowFocused); 619 if (wasFocused) onFocusChanged(true, 0, null); 620 } 621 622 /** 623 * Deletes the native counterpart of this object. Normally happens immediately, 624 * but maybe deferred until the appropriate time for GL resource cleanup. Either way 625 * this is transparent to the caller: after this function returns the object is 626 * effectively dead and methods are no-ops. 627 */ 628 public void destroy() { 629 if (mCleanupReference != null) { 630 // We explicitly do not null out the mContentViewCore reference here 631 // because ContentViewCore already has code to deal with the case 632 // methods are called on it after it's been destroyed, and other 633 // code relies on AwContents.mContentViewCore to be non-null. 634 mContentViewCore.destroy(); 635 mNativeAwContents = 0; 636 637 // We cannot destroy immediately if we are still attached to the window. 638 // Instead if we make sure to null out the native pointer so there is no more native 639 // calls, and delay the actual destroy until onDetachedFromWindow. 640 if (mIsAttachedToWindow) { 641 if (mPendingDetachCleanupReferences == null) { 642 mPendingDetachCleanupReferences = new ArrayList<CleanupReference>(); 643 } 644 mPendingDetachCleanupReferences.add(mCleanupReference); 645 } else { 646 mCleanupReference.cleanupNow(); 647 } 648 mCleanupReference = null; 649 } 650 651 assert !mContentViewCore.isAlive(); 652 assert mNativeAwContents == 0; 653 } 654 655 @VisibleForTesting 656 public ContentViewCore getContentViewCore() { 657 return mContentViewCore; 658 } 659 660 // Can be called from any thread. 661 public AwSettings getSettings() { 662 return mSettings; 663 } 664 665 public AwPdfExporter getPdfExporter() { 666 // mNativeAwContents can be null, due to destroy(). 667 if (mNativeAwContents == 0) { 668 return null; 669 } 670 if (mAwPdfExporter == null) { 671 mAwPdfExporter = new AwPdfExporter(mContainerView); 672 nativeCreatePdfExporter(mNativeAwContents, mAwPdfExporter); 673 } 674 return mAwPdfExporter; 675 } 676 677 public static void setAwDrawSWFunctionTable(int functionTablePointer) { 678 nativeSetAwDrawSWFunctionTable(functionTablePointer); 679 } 680 681 public static void setAwDrawGLFunctionTable(int functionTablePointer) { 682 nativeSetAwDrawGLFunctionTable(functionTablePointer); 683 } 684 685 public static int getAwDrawGLFunction() { 686 return nativeGetAwDrawGLFunction(); 687 } 688 689 public static void setShouldDownloadFavicons() { 690 nativeSetShouldDownloadFavicons(); 691 } 692 693 /** 694 * Intended for test code. 695 * @return the number of native instances of this class. 696 */ 697 @VisibleForTesting 698 public static int getNativeInstanceCount() { 699 return nativeGetNativeInstanceCount(); 700 } 701 702 public int getAwDrawGLViewContext() { 703 // Only called during early construction, so client should not have had a chance to 704 // call destroy yet. 705 assert mNativeAwContents != 0; 706 707 // Using the native pointer as the returned viewContext. This is matched by the 708 // reinterpret_cast back to BrowserViewRenderer pointer in the native DrawGLFunction. 709 return nativeGetAwDrawGLViewContext(mNativeAwContents); 710 } 711 712 // This is only to avoid heap allocations inside updateGLobalVisibleRect. It should treated 713 // as a local variable in the function and not used anywhere else. 714 private static final Rect sLocalGlobalVisibleRect = new Rect(); 715 716 @CalledByNative 717 private void updateGlobalVisibleRect() { 718 if (mNativeAwContents == 0) return; 719 if (!mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect)) { 720 sLocalGlobalVisibleRect.setEmpty(); 721 } 722 723 nativeSetGlobalVisibleRect(mNativeAwContents, sLocalGlobalVisibleRect.left, 724 sLocalGlobalVisibleRect.top, sLocalGlobalVisibleRect.right, 725 sLocalGlobalVisibleRect.bottom); 726 } 727 728 //-------------------------------------------------------------------------------------------- 729 // WebView[Provider] method implementations (where not provided by ContentViewCore) 730 //-------------------------------------------------------------------------------------------- 731 732 // Only valid within onDraw(). 733 private final Rect mClipBoundsTemporary = new Rect(); 734 735 public void onDraw(Canvas canvas) { 736 if (mNativeAwContents == 0) { 737 canvas.drawColor(getEffectiveBackgroundColor()); 738 return; 739 } 740 741 mScrollOffsetManager.syncScrollOffsetFromOnDraw(); 742 canvas.getClipBounds(mClipBoundsTemporary); 743 744 if (!nativeOnDraw(mNativeAwContents, canvas, canvas.isHardwareAccelerated(), 745 mContainerView.getScrollX(), mContainerView.getScrollY(), 746 mClipBoundsTemporary.left, mClipBoundsTemporary.top, 747 mClipBoundsTemporary.right, mClipBoundsTemporary.bottom)) { 748 // Can happen during initialization when compositor is not set up. Or when clearView 749 // is in effect. Just draw background color instead. 750 canvas.drawColor(getEffectiveBackgroundColor()); 751 } 752 753 if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas, 754 mScrollOffsetManager.computeMaximumHorizontalScrollOffset(), 755 mScrollOffsetManager.computeMaximumVerticalScrollOffset())) { 756 mContainerView.invalidate(); 757 } 758 } 759 760 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 761 mLayoutSizer.onMeasure(widthMeasureSpec, heightMeasureSpec); 762 } 763 764 public int getContentHeightCss() { 765 return (int) Math.ceil(mContentHeightDip); 766 } 767 768 public int getContentWidthCss() { 769 return (int) Math.ceil(mContentWidthDip); 770 } 771 772 public Picture capturePicture() { 773 if (mNativeAwContents == 0) return null; 774 return new AwPicture(nativeCapturePicture(mNativeAwContents, 775 mScrollOffsetManager.computeHorizontalScrollRange(), 776 mScrollOffsetManager.computeVerticalScrollRange())); 777 } 778 779 public void clearView() { 780 if (mNativeAwContents == 0) return; 781 nativeClearView(mNativeAwContents); 782 } 783 784 /** 785 * Enable the onNewPicture callback. 786 * @param enabled Flag to enable the callback. 787 * @param invalidationOnly Flag to call back only on invalidation without providing a picture. 788 */ 789 public void enableOnNewPicture(boolean enabled, boolean invalidationOnly) { 790 if (mNativeAwContents == 0) return; 791 if (invalidationOnly) { 792 mPictureListenerContentProvider = null; 793 } else if (enabled && mPictureListenerContentProvider == null) { 794 mPictureListenerContentProvider = new Callable<Picture>() { 795 @Override 796 public Picture call() { 797 return capturePicture(); 798 } 799 }; 800 } 801 nativeEnableOnNewPicture(mNativeAwContents, enabled); 802 } 803 804 public void findAllAsync(String searchString) { 805 if (mNativeAwContents == 0) return; 806 nativeFindAllAsync(mNativeAwContents, searchString); 807 } 808 809 public void findNext(boolean forward) { 810 if (mNativeAwContents == 0) return; 811 nativeFindNext(mNativeAwContents, forward); 812 } 813 814 public void clearMatches() { 815 if (mNativeAwContents == 0) return; 816 nativeClearMatches(mNativeAwContents); 817 } 818 819 /** 820 * @return load progress of the WebContents. 821 */ 822 public int getMostRecentProgress() { 823 // WebContentsDelegateAndroid conveniently caches the most recent notified value for us. 824 return mWebContentsDelegate.getMostRecentProgress(); 825 } 826 827 public Bitmap getFavicon() { 828 return mFavicon; 829 } 830 831 private void requestVisitedHistoryFromClient() { 832 ValueCallback<String[]> callback = new ValueCallback<String[]>() { 833 @Override 834 public void onReceiveValue(final String[] value) { 835 ThreadUtils.runOnUiThread(new Runnable() { 836 @Override 837 public void run() { 838 if (mNativeAwContents == 0) return; 839 nativeAddVisitedLinks(mNativeAwContents, value); 840 } 841 }); 842 } 843 }; 844 mContentsClient.getVisitedHistory(callback); 845 } 846 847 /** 848 * Load url without fixing up the url string. Consumers of ContentView are responsible for 849 * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left 850 * off during user input). 851 * 852 * @param params Parameters for this load. 853 */ 854 public void loadUrl(LoadUrlParams params) { 855 if (params.getLoadUrlType() == LoadUrlParams.LOAD_TYPE_DATA && 856 !params.isBaseUrlDataScheme()) { 857 // This allows data URLs with a non-data base URL access to file:///android_asset/ and 858 // file:///android_res/ URLs. If AwSettings.getAllowFileAccess permits, it will also 859 // allow access to file:// URLs (subject to OS level permission checks). 860 params.setCanLoadLocalResources(true); 861 } 862 863 // If we are reloading the same url, then set transition type as reload. 864 if (params.getUrl() != null && 865 params.getUrl().equals(mContentViewCore.getUrl()) && 866 params.getTransitionType() == PageTransitionTypes.PAGE_TRANSITION_LINK) { 867 params.setTransitionType(PageTransitionTypes.PAGE_TRANSITION_RELOAD); 868 } 869 params.setTransitionType( 870 params.getTransitionType() | PageTransitionTypes.PAGE_TRANSITION_FROM_API); 871 872 // For WebView, always use the user agent override, which is set 873 // every time the user agent in AwSettings is modified. 874 params.setOverrideUserAgent(LoadUrlParams.UA_OVERRIDE_TRUE); 875 876 // We don't pass extra headers to the content layer, as WebViewClassic 877 // was adding them in a very narrow set of conditions. See http://crbug.com/306873 878 if (mNativeAwContents != 0) { 879 nativeSetExtraHeadersForUrl( 880 mNativeAwContents, params.getUrl(), params.getExtraHttpRequestHeadersString()); 881 } 882 params.setExtraHeaders(new HashMap<String, String>()); 883 884 mContentViewCore.loadUrl(params); 885 886 // The behavior of WebViewClassic uses the populateVisitedLinks callback in WebKit. 887 // Chromium does not use this use code path and the best emulation of this behavior to call 888 // request visited links once on the first URL load of the WebView. 889 if (!mHasRequestedVisitedHistoryFromClient) { 890 mHasRequestedVisitedHistoryFromClient = true; 891 requestVisitedHistoryFromClient(); 892 } 893 894 if (params.getLoadUrlType() == LoadUrlParams.LOAD_TYPE_DATA && 895 params.getBaseUrl() != null) { 896 // Data loads with a base url will be resolved in Blink, and not cause an onPageStarted 897 // event to be sent. Sending the callback directly from here. 898 mContentsClient.getCallbackHelper().postOnPageStarted(params.getBaseUrl()); 899 } 900 } 901 902 /** 903 * Get the URL of the current page. 904 * 905 * @return The URL of the current page or null if it's empty. 906 */ 907 public String getUrl() { 908 String url = mContentViewCore.getUrl(); 909 if (url == null || url.trim().isEmpty()) return null; 910 return url; 911 } 912 913 public void requestFocus() { 914 if (mNativeAwContents == 0) return; 915 if (!mContainerView.isInTouchMode() && mSettings.shouldFocusFirstNode()) { 916 nativeFocusFirstNode(mNativeAwContents); 917 } 918 } 919 920 public void setBackgroundColor(int color) { 921 mBaseBackgroundColor = color; 922 if (mNativeAwContents != 0) nativeSetBackgroundColor(mNativeAwContents, color); 923 } 924 925 private int getEffectiveBackgroundColor() { 926 // Do not ask the ContentViewCore for the background color, as it will always 927 // report white prior to initial navigation or post destruction, whereas we want 928 // to use the client supplied base value in those cases. 929 if (mNativeAwContents == 0 || !mContentsClient.isCachedRendererBackgroundColorValid()) { 930 return mBaseBackgroundColor; 931 } 932 return mContentsClient.getCachedRendererBackgroundColor(); 933 } 934 935 public boolean isMultiTouchZoomSupported() { 936 return mSettings.supportsMultiTouchZoom(); 937 } 938 939 public View getZoomControlsForTest() { 940 return mZoomControls.getZoomControlsViewForTest(); 941 } 942 943 /** 944 * @see ContentViewCore#getContentSettings() 945 */ 946 public ContentSettings getContentSettings() { 947 return mContentViewCore.getContentSettings(); 948 } 949 950 /** 951 * @see View#setOverScrollMode(int) 952 */ 953 public void setOverScrollMode(int mode) { 954 if (mode != View.OVER_SCROLL_NEVER) { 955 mOverScrollGlow = new OverScrollGlow(mContainerView); 956 } else { 957 mOverScrollGlow = null; 958 } 959 } 960 961 // TODO(mkosiba): In WebViewClassic these appear in some of the scroll extent calculation 962 // methods but toggling them has no visiual effect on the content (in other words the scrolling 963 // code behaves as if the scrollbar-related padding is in place but the onDraw code doesn't 964 // take that into consideration). 965 // http://crbug.com/269032 966 private boolean mOverlayHorizontalScrollbar = true; 967 private boolean mOverlayVerticalScrollbar = false; 968 969 /** 970 * @see View#setScrollBarStyle(int) 971 */ 972 public void setScrollBarStyle(int style) { 973 if (style == View.SCROLLBARS_INSIDE_OVERLAY 974 || style == View.SCROLLBARS_OUTSIDE_OVERLAY) { 975 mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true; 976 } else { 977 mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false; 978 } 979 } 980 981 /** 982 * @see View#setHorizontalScrollbarOverlay(boolean) 983 */ 984 public void setHorizontalScrollbarOverlay(boolean overlay) { 985 mOverlayHorizontalScrollbar = overlay; 986 } 987 988 /** 989 * @see View#setVerticalScrollbarOverlay(boolean) 990 */ 991 public void setVerticalScrollbarOverlay(boolean overlay) { 992 mOverlayVerticalScrollbar = overlay; 993 } 994 995 /** 996 * @see View#overlayHorizontalScrollbar() 997 */ 998 public boolean overlayHorizontalScrollbar() { 999 return mOverlayHorizontalScrollbar; 1000 } 1001 1002 /** 1003 * @see View#overlayVerticalScrollbar() 1004 */ 1005 public boolean overlayVerticalScrollbar() { 1006 return mOverlayVerticalScrollbar; 1007 } 1008 1009 /** 1010 * Called by the embedder when the scroll offset of the containing view has changed. 1011 * @see View#onScrollChanged(int,int) 1012 */ 1013 public void onContainerViewScrollChanged(int l, int t, int oldl, int oldt) { 1014 // A side-effect of View.onScrollChanged is that the scroll accessibility event being sent 1015 // by the base class implementation. This is completely hidden from the base classes and 1016 // cannot be prevented, which is why we need the code below. 1017 mScrollAccessibilityHelper.removePostedViewScrolledAccessibilityEventCallback(); 1018 mScrollOffsetManager.onContainerViewScrollChanged(l, t); 1019 } 1020 1021 /** 1022 * Called by the embedder when the containing view is to be scrolled or overscrolled. 1023 * @see View#onOverScrolled(int,int,int,int) 1024 */ 1025 public void onContainerViewOverScrolled(int scrollX, int scrollY, boolean clampedX, 1026 boolean clampedY) { 1027 int oldX = mContainerView.getScrollX(); 1028 int oldY = mContainerView.getScrollY(); 1029 1030 mScrollOffsetManager.onContainerViewOverScrolled(scrollX, scrollY, clampedX, clampedY); 1031 1032 if (mOverScrollGlow != null) { 1033 mOverScrollGlow.pullGlow(mContainerView.getScrollX(), mContainerView.getScrollY(), 1034 oldX, oldY, 1035 mScrollOffsetManager.computeMaximumHorizontalScrollOffset(), 1036 mScrollOffsetManager.computeMaximumVerticalScrollOffset()); 1037 } 1038 } 1039 1040 /** 1041 * @see android.webkit.WebView#requestChildRectangleOnScreen(View, Rect, boolean) 1042 */ 1043 public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { 1044 return mScrollOffsetManager.requestChildRectangleOnScreen( 1045 child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY(), 1046 rect, immediate); 1047 } 1048 1049 /** 1050 * @see View.computeScroll() 1051 */ 1052 public void computeScroll() { 1053 mScrollOffsetManager.computeScrollAndAbsorbGlow(mOverScrollGlow); 1054 } 1055 1056 /** 1057 * @see View#computeHorizontalScrollRange() 1058 */ 1059 public int computeHorizontalScrollRange() { 1060 return mScrollOffsetManager.computeHorizontalScrollRange(); 1061 } 1062 1063 /** 1064 * @see View#computeHorizontalScrollOffset() 1065 */ 1066 public int computeHorizontalScrollOffset() { 1067 return mScrollOffsetManager.computeHorizontalScrollOffset(); 1068 } 1069 1070 /** 1071 * @see View#computeVerticalScrollRange() 1072 */ 1073 public int computeVerticalScrollRange() { 1074 return mScrollOffsetManager.computeVerticalScrollRange(); 1075 } 1076 1077 /** 1078 * @see View#computeVerticalScrollOffset() 1079 */ 1080 public int computeVerticalScrollOffset() { 1081 return mScrollOffsetManager.computeVerticalScrollOffset(); 1082 } 1083 1084 /** 1085 * @see View#computeVerticalScrollExtent() 1086 */ 1087 public int computeVerticalScrollExtent() { 1088 return mScrollOffsetManager.computeVerticalScrollExtent(); 1089 } 1090 1091 /** 1092 * @see android.webkit.WebView#stopLoading() 1093 */ 1094 public void stopLoading() { 1095 mContentViewCore.stopLoading(); 1096 } 1097 1098 /** 1099 * @see android.webkit.WebView#reload() 1100 */ 1101 public void reload() { 1102 mContentViewCore.reload(true); 1103 } 1104 1105 /** 1106 * @see android.webkit.WebView#canGoBack() 1107 */ 1108 public boolean canGoBack() { 1109 return mContentViewCore.canGoBack(); 1110 } 1111 1112 /** 1113 * @see android.webkit.WebView#goBack() 1114 */ 1115 public void goBack() { 1116 mContentViewCore.goBack(); 1117 } 1118 1119 /** 1120 * @see android.webkit.WebView#canGoForward() 1121 */ 1122 public boolean canGoForward() { 1123 return mContentViewCore.canGoForward(); 1124 } 1125 1126 /** 1127 * @see android.webkit.WebView#goForward() 1128 */ 1129 public void goForward() { 1130 mContentViewCore.goForward(); 1131 } 1132 1133 /** 1134 * @see android.webkit.WebView#canGoBackOrForward(int) 1135 */ 1136 public boolean canGoBackOrForward(int steps) { 1137 return mContentViewCore.canGoToOffset(steps); 1138 } 1139 1140 /** 1141 * @see android.webkit.WebView#goBackOrForward(int) 1142 */ 1143 public void goBackOrForward(int steps) { 1144 mContentViewCore.goToOffset(steps); 1145 } 1146 1147 /** 1148 * @see android.webkit.WebView#pauseTimers() 1149 */ 1150 public void pauseTimers() { 1151 ContentViewStatics.setWebKitSharedTimersSuspended(true); 1152 } 1153 1154 /** 1155 * @see android.webkit.WebView#resumeTimers() 1156 */ 1157 public void resumeTimers() { 1158 ContentViewStatics.setWebKitSharedTimersSuspended(false); 1159 } 1160 1161 /** 1162 * @see android.webkit.WebView#onPause() 1163 */ 1164 public void onPause() { 1165 if (mIsPaused || mNativeAwContents == 0) return; 1166 mIsPaused = true; 1167 nativeSetIsPaused(mNativeAwContents, mIsPaused); 1168 } 1169 1170 /** 1171 * @see android.webkit.WebView#onResume() 1172 */ 1173 public void onResume() { 1174 if (!mIsPaused || mNativeAwContents == 0) return; 1175 mIsPaused = false; 1176 nativeSetIsPaused(mNativeAwContents, mIsPaused); 1177 } 1178 1179 /** 1180 * @see android.webkit.WebView#isPaused() 1181 */ 1182 public boolean isPaused() { 1183 return mIsPaused; 1184 } 1185 1186 /** 1187 * @see android.webkit.WebView#onCreateInputConnection(EditorInfo) 1188 */ 1189 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 1190 return mContentViewCore.onCreateInputConnection(outAttrs); 1191 } 1192 1193 /** 1194 * @see android.webkit.WebView#onKeyUp(int, KeyEvent) 1195 */ 1196 public boolean onKeyUp(int keyCode, KeyEvent event) { 1197 return mContentViewCore.onKeyUp(keyCode, event); 1198 } 1199 1200 private boolean isDpadEvent(KeyEvent event) { 1201 if (event.getAction() == KeyEvent.ACTION_DOWN) { 1202 switch (event.getKeyCode()) { 1203 case KeyEvent.KEYCODE_DPAD_CENTER: 1204 case KeyEvent.KEYCODE_DPAD_DOWN: 1205 case KeyEvent.KEYCODE_DPAD_UP: 1206 case KeyEvent.KEYCODE_DPAD_LEFT: 1207 case KeyEvent.KEYCODE_DPAD_RIGHT: 1208 return true; 1209 } 1210 } 1211 return false; 1212 } 1213 1214 /** 1215 * @see android.webkit.WebView#dispatchKeyEvent(KeyEvent) 1216 */ 1217 public boolean dispatchKeyEvent(KeyEvent event) { 1218 if (isDpadEvent(event)) { 1219 mSettings.setSpatialNavigationEnabled(true); 1220 } 1221 return mContentViewCore.dispatchKeyEvent(event); 1222 } 1223 1224 /** 1225 * Clears the resource cache. Note that the cache is per-application, so this will clear the 1226 * cache for all WebViews used. 1227 * 1228 * @param includeDiskFiles if false, only the RAM cache is cleared 1229 */ 1230 public void clearCache(boolean includeDiskFiles) { 1231 if (mNativeAwContents == 0) return; 1232 nativeClearCache(mNativeAwContents, includeDiskFiles); 1233 } 1234 1235 public void documentHasImages(Message message) { 1236 if (mNativeAwContents == 0) return; 1237 nativeDocumentHasImages(mNativeAwContents, message); 1238 } 1239 1240 public void saveWebArchive( 1241 final String basename, boolean autoname, final ValueCallback<String> callback) { 1242 if (!autoname) { 1243 saveWebArchiveInternal(basename, callback); 1244 return; 1245 } 1246 // If auto-generating the file name, handle the name generation on a background thread 1247 // as it will require I/O access for checking whether previous files existed. 1248 new AsyncTask<Void, Void, String>() { 1249 @Override 1250 protected String doInBackground(Void... params) { 1251 return generateArchiveAutoNamePath(getOriginalUrl(), basename); 1252 } 1253 1254 @Override 1255 protected void onPostExecute(String result) { 1256 saveWebArchiveInternal(result, callback); 1257 } 1258 }.execute(); 1259 } 1260 1261 public String getOriginalUrl() { 1262 NavigationHistory history = mContentViewCore.getNavigationHistory(); 1263 int currentIndex = history.getCurrentEntryIndex(); 1264 if (currentIndex >= 0 && currentIndex < history.getEntryCount()) { 1265 return history.getEntryAtIndex(currentIndex).getOriginalUrl(); 1266 } 1267 return null; 1268 } 1269 1270 /** 1271 * @see ContentViewCore#getNavigationHistory() 1272 */ 1273 public NavigationHistory getNavigationHistory() { 1274 return mContentViewCore.getNavigationHistory(); 1275 } 1276 1277 /** 1278 * @see android.webkit.WebView#getTitle() 1279 */ 1280 public String getTitle() { 1281 return mContentViewCore.getTitle(); 1282 } 1283 1284 /** 1285 * @see android.webkit.WebView#clearHistory() 1286 */ 1287 public void clearHistory() { 1288 mContentViewCore.clearHistory(); 1289 } 1290 1291 public String[] getHttpAuthUsernamePassword(String host, String realm) { 1292 return mBrowserContext.getHttpAuthDatabase(mContentViewCore.getContext()) 1293 .getHttpAuthUsernamePassword(host, realm); 1294 } 1295 1296 public void setHttpAuthUsernamePassword(String host, String realm, String username, 1297 String password) { 1298 mBrowserContext.getHttpAuthDatabase(mContentViewCore.getContext()) 1299 .setHttpAuthUsernamePassword(host, realm, username, password); 1300 } 1301 1302 /** 1303 * @see android.webkit.WebView#getCertificate() 1304 */ 1305 public SslCertificate getCertificate() { 1306 if (mNativeAwContents == 0) return null; 1307 return SslUtil.getCertificateFromDerBytes(nativeGetCertificate(mNativeAwContents)); 1308 } 1309 1310 /** 1311 * @see android.webkit.WebView#clearSslPreferences() 1312 */ 1313 public void clearSslPreferences() { 1314 mContentViewCore.clearSslPreferences(); 1315 } 1316 1317 /** 1318 * Method to return all hit test values relevant to public WebView API. 1319 * Note that this expose more data than needed for WebView.getHitTestResult. 1320 * Unsafely returning reference to mutable internal object to avoid excessive 1321 * garbage allocation on repeated calls. 1322 */ 1323 public HitTestData getLastHitTestResult() { 1324 if (mNativeAwContents == 0) return null; 1325 nativeUpdateLastHitTestData(mNativeAwContents); 1326 return mPossiblyStaleHitTestData; 1327 } 1328 1329 /** 1330 * @see android.webkit.WebView#requestFocusNodeHref() 1331 */ 1332 public void requestFocusNodeHref(Message msg) { 1333 if (msg == null || mNativeAwContents == 0) return; 1334 1335 nativeUpdateLastHitTestData(mNativeAwContents); 1336 Bundle data = msg.getData(); 1337 1338 // In order to maintain compatibility with the old WebView's implementation, 1339 // the absolute (full) url is passed in the |url| field, not only the href attribute. 1340 // Note: HitTestData could be cleaned up at this point. See http://crbug.com/290992. 1341 data.putString("url", mPossiblyStaleHitTestData.href); 1342 data.putString("title", mPossiblyStaleHitTestData.anchorText); 1343 data.putString("src", mPossiblyStaleHitTestData.imgSrc); 1344 msg.setData(data); 1345 msg.sendToTarget(); 1346 } 1347 1348 /** 1349 * @see android.webkit.WebView#requestImageRef() 1350 */ 1351 public void requestImageRef(Message msg) { 1352 if (msg == null || mNativeAwContents == 0) return; 1353 1354 nativeUpdateLastHitTestData(mNativeAwContents); 1355 Bundle data = msg.getData(); 1356 data.putString("url", mPossiblyStaleHitTestData.imgSrc); 1357 msg.setData(data); 1358 msg.sendToTarget(); 1359 } 1360 1361 @VisibleForTesting 1362 public float getPageScaleFactor() { 1363 return mPageScaleFactor; 1364 } 1365 1366 /** 1367 * @see android.webkit.WebView#getScale() 1368 * 1369 * Please note that the scale returned is the page scale multiplied by 1370 * the screen density factor. See CTS WebViewTest.testSetInitialScale. 1371 */ 1372 public float getScale() { 1373 return (float)(mPageScaleFactor * mDIPScale); 1374 } 1375 1376 /** 1377 * @see android.webkit.WebView#flingScroll(int, int) 1378 */ 1379 public void flingScroll(int velocityX, int velocityY) { 1380 mScrollOffsetManager.flingScroll(velocityX, velocityY); 1381 } 1382 1383 /** 1384 * @see android.webkit.WebView#pageUp(boolean) 1385 */ 1386 public boolean pageUp(boolean top) { 1387 return mScrollOffsetManager.pageUp(top); 1388 } 1389 1390 /** 1391 * @see android.webkit.WebView#pageDown(boolean) 1392 */ 1393 public boolean pageDown(boolean bottom) { 1394 return mScrollOffsetManager.pageDown(bottom); 1395 } 1396 1397 /** 1398 * @see android.webkit.WebView#canZoomIn() 1399 */ 1400 // This method uses the term 'zoom' for legacy reasons, but relates 1401 // to what chrome calls the 'page scale factor'. 1402 public boolean canZoomIn() { 1403 final float zoomInExtent = mMaxPageScaleFactor - mPageScaleFactor; 1404 return zoomInExtent > ZOOM_CONTROLS_EPSILON; 1405 } 1406 1407 /** 1408 * @see android.webkit.WebView#canZoomOut() 1409 */ 1410 // This method uses the term 'zoom' for legacy reasons, but relates 1411 // to what chrome calls the 'page scale factor'. 1412 public boolean canZoomOut() { 1413 final float zoomOutExtent = mPageScaleFactor - mMinPageScaleFactor; 1414 return zoomOutExtent > ZOOM_CONTROLS_EPSILON; 1415 } 1416 1417 /** 1418 * @see android.webkit.WebView#zoomIn() 1419 */ 1420 // This method uses the term 'zoom' for legacy reasons, but relates 1421 // to what chrome calls the 'page scale factor'. 1422 public boolean zoomIn() { 1423 if (!canZoomIn()) { 1424 return false; 1425 } 1426 return mContentViewCore.pinchByDelta(1.25f); 1427 } 1428 1429 /** 1430 * @see android.webkit.WebView#zoomOut() 1431 */ 1432 // This method uses the term 'zoom' for legacy reasons, but relates 1433 // to what chrome calls the 'page scale factor'. 1434 public boolean zoomOut() { 1435 if (!canZoomOut()) { 1436 return false; 1437 } 1438 return mContentViewCore.pinchByDelta(0.8f); 1439 } 1440 1441 /** 1442 * @see android.webkit.WebView#invokeZoomPicker() 1443 */ 1444 public void invokeZoomPicker() { 1445 mContentViewCore.invokeZoomPicker(); 1446 } 1447 1448 /** 1449 * @see ContentViewCore.evaluateJavaScript(String, ContentViewCore.JavaScriptCallback) 1450 */ 1451 public void evaluateJavaScript(String script, final ValueCallback<String> callback) { 1452 ContentViewCore.JavaScriptCallback jsCallback = null; 1453 if (callback != null) { 1454 jsCallback = new ContentViewCore.JavaScriptCallback() { 1455 @Override 1456 public void handleJavaScriptResult(String jsonResult) { 1457 callback.onReceiveValue(jsonResult); 1458 } 1459 }; 1460 } 1461 1462 mContentViewCore.evaluateJavaScript(script, jsCallback); 1463 } 1464 1465 /** 1466 * @see ContentViewCore.evaluateJavaScriptEvenIfNotYetNavigated(String) 1467 */ 1468 public void evaluateJavaScriptEvenIfNotYetNavigated(String script) { 1469 mContentViewCore.evaluateJavaScriptEvenIfNotYetNavigated(script); 1470 } 1471 1472 //-------------------------------------------------------------------------------------------- 1473 // View and ViewGroup method implementations 1474 //-------------------------------------------------------------------------------------------- 1475 1476 /** 1477 * @see android.webkit.View#onTouchEvent() 1478 */ 1479 public boolean onTouchEvent(MotionEvent event) { 1480 if (mNativeAwContents == 0) return false; 1481 1482 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 1483 mSettings.setSpatialNavigationEnabled(false); 1484 } 1485 1486 mScrollOffsetManager.setProcessingTouchEvent(true); 1487 boolean rv = mContentViewCore.onTouchEvent(event); 1488 mScrollOffsetManager.setProcessingTouchEvent(false); 1489 1490 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 1491 int actionIndex = event.getActionIndex(); 1492 1493 // Note this will trigger IPC back to browser even if nothing is hit. 1494 nativeRequestNewHitTestDataAt(mNativeAwContents, 1495 (int) Math.round(event.getX(actionIndex) / mDIPScale), 1496 (int) Math.round(event.getY(actionIndex) / mDIPScale)); 1497 } 1498 1499 if (mOverScrollGlow != null && event.getActionMasked() == MotionEvent.ACTION_UP) { 1500 mOverScrollGlow.releaseAll(); 1501 } 1502 1503 return rv; 1504 } 1505 1506 /** 1507 * @see android.view.View#onHoverEvent() 1508 */ 1509 public boolean onHoverEvent(MotionEvent event) { 1510 return mContentViewCore.onHoverEvent(event); 1511 } 1512 1513 /** 1514 * @see android.view.View#onGenericMotionEvent() 1515 */ 1516 public boolean onGenericMotionEvent(MotionEvent event) { 1517 return mContentViewCore.onGenericMotionEvent(event); 1518 } 1519 1520 /** 1521 * @see android.view.View#onConfigurationChanged() 1522 */ 1523 public void onConfigurationChanged(Configuration newConfig) { 1524 mContentViewCore.onConfigurationChanged(newConfig); 1525 } 1526 1527 /** 1528 * @see android.view.View#onAttachedToWindow() 1529 * 1530 * Note that this is also called from receivePopupContents. 1531 */ 1532 public void onAttachedToWindow() { 1533 if (mNativeAwContents == 0) return; 1534 mIsAttachedToWindow = true; 1535 1536 mContentViewCore.onAttachedToWindow(); 1537 nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(), 1538 mContainerView.getHeight()); 1539 mSettings.setEnableSupportedHardwareAcceleratedFeatures( 1540 mContainerView.isHardwareAccelerated()); 1541 1542 if (mComponentCallbacks != null) return; 1543 mComponentCallbacks = new AwComponentCallbacks(); 1544 mContainerView.getContext().registerComponentCallbacks(mComponentCallbacks); 1545 } 1546 1547 /** 1548 * @see android.view.View#onDetachedFromWindow() 1549 */ 1550 public void onDetachedFromWindow() { 1551 mIsAttachedToWindow = false; 1552 hideAutofillPopup(); 1553 if (mNativeAwContents != 0) { 1554 nativeOnDetachedFromWindow(mNativeAwContents); 1555 } 1556 1557 mContentViewCore.onDetachedFromWindow(); 1558 1559 mSettings.setEnableSupportedHardwareAcceleratedFeatures(false); 1560 1561 if (mComponentCallbacks != null) { 1562 mContainerView.getContext().unregisterComponentCallbacks(mComponentCallbacks); 1563 mComponentCallbacks = null; 1564 } 1565 1566 mScrollAccessibilityHelper.removePostedCallbacks(); 1567 1568 if (mPendingDetachCleanupReferences != null) { 1569 for (int i = 0; i < mPendingDetachCleanupReferences.size(); ++i) { 1570 mPendingDetachCleanupReferences.get(i).cleanupNow(); 1571 } 1572 mPendingDetachCleanupReferences = null; 1573 } 1574 } 1575 1576 /** 1577 * @see android.view.View#onWindowFocusChanged() 1578 */ 1579 public void onWindowFocusChanged(boolean hasWindowFocus) { 1580 mWindowFocused = hasWindowFocus; 1581 mContentViewCore.onWindowFocusChanged(hasWindowFocus); 1582 } 1583 1584 /** 1585 * @see android.view.View#onFocusChanged() 1586 */ 1587 public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { 1588 mContainerViewFocused = focused; 1589 mContentViewCore.onFocusChanged(focused); 1590 } 1591 1592 /** 1593 * @see android.view.View#onSizeChanged() 1594 */ 1595 public void onSizeChanged(int w, int h, int ow, int oh) { 1596 if (mNativeAwContents == 0) return; 1597 mScrollOffsetManager.setContainerViewSize(w, h); 1598 // The AwLayoutSizer needs to go first so that if we're in fixedLayoutSize mode the update 1599 // to enter fixedLayoutSize mode is sent before the first resize update. 1600 mLayoutSizer.onSizeChanged(w, h, ow, oh); 1601 mContentViewCore.onPhysicalBackingSizeChanged(w, h); 1602 mContentViewCore.onSizeChanged(w, h, ow, oh); 1603 nativeOnSizeChanged(mNativeAwContents, w, h, ow, oh); 1604 } 1605 1606 /** 1607 * @see android.view.View#onVisibilityChanged() 1608 */ 1609 public void onVisibilityChanged(View changedView, int visibility) { 1610 boolean viewVisible = mContainerView.getVisibility() == View.VISIBLE; 1611 if (mIsViewVisible == viewVisible) return; 1612 setViewVisibilityInternal(viewVisible); 1613 } 1614 1615 /** 1616 * @see android.view.View#onWindowVisibilityChanged() 1617 */ 1618 public void onWindowVisibilityChanged(int visibility) { 1619 boolean windowVisible = visibility == View.VISIBLE; 1620 if (mIsWindowVisible == windowVisible) return; 1621 setWindowVisibilityInternal(windowVisible); 1622 } 1623 1624 private void setViewVisibilityInternal(boolean visible) { 1625 mIsViewVisible = visible; 1626 if (mNativeAwContents == 0) return; 1627 nativeSetViewVisibility(mNativeAwContents, mIsViewVisible); 1628 } 1629 1630 private void setWindowVisibilityInternal(boolean visible) { 1631 mIsWindowVisible = visible; 1632 if (mNativeAwContents == 0) return; 1633 nativeSetWindowVisibility(mNativeAwContents, mIsWindowVisible); 1634 } 1635 1636 /** 1637 * Key for opaque state in bundle. Note this is only public for tests. 1638 */ 1639 public static final String SAVE_RESTORE_STATE_KEY = "WEBVIEW_CHROMIUM_STATE"; 1640 1641 /** 1642 * Save the state of this AwContents into provided Bundle. 1643 * @return False if saving state failed. 1644 */ 1645 public boolean saveState(Bundle outState) { 1646 if (mNativeAwContents == 0 || outState == null) return false; 1647 1648 byte[] state = nativeGetOpaqueState(mNativeAwContents); 1649 if (state == null) return false; 1650 1651 outState.putByteArray(SAVE_RESTORE_STATE_KEY, state); 1652 return true; 1653 } 1654 1655 /** 1656 * Restore the state of this AwContents into provided Bundle. 1657 * @param inState Must be a bundle returned by saveState. 1658 * @return False if restoring state failed. 1659 */ 1660 public boolean restoreState(Bundle inState) { 1661 if (mNativeAwContents == 0 || inState == null) return false; 1662 1663 byte[] state = inState.getByteArray(SAVE_RESTORE_STATE_KEY); 1664 if (state == null) return false; 1665 1666 boolean result = nativeRestoreFromOpaqueState(mNativeAwContents, state); 1667 1668 // The onUpdateTitle callback normally happens when a page is loaded, 1669 // but is optimized out in the restoreState case because the title is 1670 // already restored. See WebContentsImpl::UpdateTitleForEntry. So we 1671 // call the callback explicitly here. 1672 if (result) mContentsClient.onReceivedTitle(mContentViewCore.getTitle()); 1673 1674 return result; 1675 } 1676 1677 /** 1678 * @see ContentViewCore#addPossiblyUnsafeJavascriptInterface(Object, String, Class) 1679 */ 1680 public void addPossiblyUnsafeJavascriptInterface(Object object, String name, 1681 Class<? extends Annotation> requiredAnnotation) { 1682 mContentViewCore.addPossiblyUnsafeJavascriptInterface(object, name, requiredAnnotation); 1683 } 1684 1685 /** 1686 * @see android.webkit.WebView#removeJavascriptInterface(String) 1687 */ 1688 public void removeJavascriptInterface(String interfaceName) { 1689 mContentViewCore.removeJavascriptInterface(interfaceName); 1690 } 1691 1692 /** 1693 * If native accessibility (not script injection) is enabled, and if this is 1694 * running on JellyBean or later, returns an AccessibilityNodeProvider that 1695 * implements native accessibility for this view. Returns null otherwise. 1696 * @return The AccessibilityNodeProvider, if available, or null otherwise. 1697 */ 1698 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 1699 return mContentViewCore.getAccessibilityNodeProvider(); 1700 } 1701 1702 /** 1703 * @see android.webkit.WebView#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 1704 */ 1705 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 1706 mContentViewCore.onInitializeAccessibilityNodeInfo(info); 1707 } 1708 1709 /** 1710 * @see android.webkit.WebView#onInitializeAccessibilityEvent(AccessibilityEvent) 1711 */ 1712 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 1713 mContentViewCore.onInitializeAccessibilityEvent(event); 1714 } 1715 1716 public boolean supportsAccessibilityAction(int action) { 1717 return mContentViewCore.supportsAccessibilityAction(action); 1718 } 1719 1720 /** 1721 * @see android.webkit.WebView#performAccessibilityAction(int, Bundle) 1722 */ 1723 public boolean performAccessibilityAction(int action, Bundle arguments) { 1724 return mContentViewCore.performAccessibilityAction(action, arguments); 1725 } 1726 1727 /** 1728 * @see android.webkit.WebView#clearFormData() 1729 */ 1730 public void hideAutofillPopup() { 1731 if (mAwAutofillManagerDelegate != null) 1732 mAwAutofillManagerDelegate.hideAutofillPopup(); 1733 } 1734 1735 public void setNetworkAvailable(boolean networkUp) { 1736 if (mNativeAwContents == 0) return; 1737 nativeSetJsOnlineProperty(mNativeAwContents, networkUp); 1738 } 1739 1740 //-------------------------------------------------------------------------------------------- 1741 // Methods called from native via JNI 1742 //-------------------------------------------------------------------------------------------- 1743 1744 @CalledByNative 1745 private static void onDocumentHasImagesResponse(boolean result, Message message) { 1746 message.arg1 = result ? 1 : 0; 1747 message.sendToTarget(); 1748 } 1749 1750 @CalledByNative 1751 private void onReceivedTouchIconUrl(String url, boolean precomposed) { 1752 mContentsClient.onReceivedTouchIconUrl(url, precomposed); 1753 } 1754 1755 @CalledByNative 1756 private void onReceivedIcon(Bitmap bitmap) { 1757 mContentsClient.onReceivedIcon(bitmap); 1758 mFavicon = bitmap; 1759 } 1760 1761 /** Callback for generateMHTML. */ 1762 @CalledByNative 1763 private static void generateMHTMLCallback( 1764 String path, long size, ValueCallback<String> callback) { 1765 if (callback == null) return; 1766 callback.onReceiveValue(size < 0 ? null : path); 1767 } 1768 1769 @CalledByNative 1770 private void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, String host, String realm) { 1771 mContentsClient.onReceivedHttpAuthRequest(handler, host, realm); 1772 } 1773 1774 private class AwGeolocationCallback implements GeolocationPermissions.Callback { 1775 1776 @Override 1777 public void invoke(final String origin, final boolean allow, final boolean retain) { 1778 ThreadUtils.runOnUiThread(new Runnable() { 1779 @Override 1780 public void run() { 1781 if (retain) { 1782 if (allow) { 1783 mBrowserContext.getGeolocationPermissions().allow(origin); 1784 } else { 1785 mBrowserContext.getGeolocationPermissions().deny(origin); 1786 } 1787 } 1788 if (mNativeAwContents == 0) return; 1789 nativeInvokeGeolocationCallback(mNativeAwContents, allow, origin); 1790 } 1791 }); 1792 } 1793 } 1794 1795 @CalledByNative 1796 private void onGeolocationPermissionsShowPrompt(String origin) { 1797 if (mNativeAwContents == 0) return; 1798 AwGeolocationPermissions permissions = mBrowserContext.getGeolocationPermissions(); 1799 // Reject if geoloaction is disabled, or the origin has a retained deny 1800 if (!mSettings.getGeolocationEnabled()) { 1801 nativeInvokeGeolocationCallback(mNativeAwContents, false, origin); 1802 return; 1803 } 1804 // Allow if the origin has a retained allow 1805 if (permissions.hasOrigin(origin)) { 1806 nativeInvokeGeolocationCallback(mNativeAwContents, permissions.isOriginAllowed(origin), 1807 origin); 1808 return; 1809 } 1810 mContentsClient.onGeolocationPermissionsShowPrompt( 1811 origin, new AwGeolocationCallback()); 1812 } 1813 1814 @CalledByNative 1815 private void onGeolocationPermissionsHidePrompt() { 1816 mContentsClient.onGeolocationPermissionsHidePrompt(); 1817 } 1818 1819 @CalledByNative 1820 public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches, 1821 boolean isDoneCounting) { 1822 mContentsClient.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting); 1823 } 1824 1825 @CalledByNative 1826 public void onNewPicture() { 1827 // Don't call capturePicture() here but instead defer it until the posted task runs within 1828 // the callback helper, to avoid doubling back into the renderer compositor in the middle 1829 // of the notification it is sending up to here. 1830 mContentsClient.getCallbackHelper().postOnNewPicture(mPictureListenerContentProvider); 1831 } 1832 1833 // Called as a result of nativeUpdateLastHitTestData. 1834 @CalledByNative 1835 private void updateHitTestData( 1836 int type, String extra, String href, String anchorText, String imgSrc) { 1837 mPossiblyStaleHitTestData.hitTestResultType = type; 1838 mPossiblyStaleHitTestData.hitTestResultExtraData = extra; 1839 mPossiblyStaleHitTestData.href = href; 1840 mPossiblyStaleHitTestData.anchorText = anchorText; 1841 mPossiblyStaleHitTestData.imgSrc = imgSrc; 1842 } 1843 1844 @CalledByNative 1845 private boolean requestDrawGL(Canvas canvas) { 1846 return mInternalAccessAdapter.requestDrawGL(canvas); 1847 } 1848 1849 private static final boolean SUPPORTS_ON_ANIMATION = 1850 Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; 1851 1852 @CalledByNative 1853 private void postInvalidateOnAnimation() { 1854 if (SUPPORTS_ON_ANIMATION) { 1855 mContainerView.postInvalidateOnAnimation(); 1856 } else { 1857 mContainerView.postInvalidate(); 1858 } 1859 } 1860 1861 @CalledByNative 1862 private int[] getLocationOnScreen() { 1863 int[] result = new int[2]; 1864 mContainerView.getLocationOnScreen(result); 1865 return result; 1866 } 1867 1868 @CalledByNative 1869 private void onWebLayoutPageScaleFactorChanged(float webLayoutPageScaleFactor) { 1870 // This change notification comes from the renderer thread, not from the cc/ impl thread. 1871 mLayoutSizer.onPageScaleChanged(webLayoutPageScaleFactor); 1872 } 1873 1874 @CalledByNative 1875 private void onWebLayoutContentsSizeChanged(int widthCss, int heightCss) { 1876 // This change notification comes from the renderer thread, not from the cc/ impl thread. 1877 mLayoutSizer.onContentSizeChanged(widthCss, heightCss); 1878 } 1879 1880 @CalledByNative 1881 private void setMaxContainerViewScrollOffset(int maxX, int maxY) { 1882 mScrollOffsetManager.setMaxScrollOffset(maxX, maxY); 1883 } 1884 1885 @CalledByNative 1886 private void scrollContainerViewTo(int x, int y) { 1887 mScrollOffsetManager.scrollContainerViewTo(x, y); 1888 } 1889 1890 @CalledByNative 1891 private boolean isFlingActive() { 1892 return mScrollOffsetManager.isFlingActive(); 1893 } 1894 1895 @CalledByNative 1896 private void setContentsSize(int widthDip, int heightDip) { 1897 mContentWidthDip = widthDip; 1898 mContentHeightDip = heightDip; 1899 } 1900 1901 @CalledByNative 1902 private void setPageScaleFactorAndLimits( 1903 float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) { 1904 if (mPageScaleFactor == pageScaleFactor && 1905 mMinPageScaleFactor == minPageScaleFactor && 1906 mMaxPageScaleFactor == maxPageScaleFactor) 1907 return; 1908 mMinPageScaleFactor = minPageScaleFactor; 1909 mMaxPageScaleFactor = maxPageScaleFactor; 1910 if (mPageScaleFactor != pageScaleFactor) { 1911 float oldPageScaleFactor = mPageScaleFactor; 1912 mPageScaleFactor = pageScaleFactor; 1913 mContentsClient.getCallbackHelper().postOnScaleChangedScaled( 1914 (float)(oldPageScaleFactor * mDIPScale), 1915 (float)(mPageScaleFactor * mDIPScale)); 1916 } 1917 } 1918 1919 @CalledByNative 1920 private void setAwAutofillManagerDelegate(AwAutofillManagerDelegate delegate) { 1921 mAwAutofillManagerDelegate = delegate; 1922 delegate.init(mContentViewCore); 1923 } 1924 1925 @CalledByNative 1926 private void didOverscroll(int deltaX, int deltaY) { 1927 if (mOverScrollGlow != null) { 1928 mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY); 1929 } 1930 1931 mScrollOffsetManager.overScrollBy(deltaX, deltaY); 1932 1933 if (mOverScrollGlow != null && mOverScrollGlow.isAnimating()) { 1934 mContainerView.invalidate(); 1935 } 1936 } 1937 1938 // ------------------------------------------------------------------------------------------- 1939 // Helper methods 1940 // ------------------------------------------------------------------------------------------- 1941 1942 private void saveWebArchiveInternal(String path, final ValueCallback<String> callback) { 1943 if (path == null || mNativeAwContents == 0) { 1944 ThreadUtils.runOnUiThread(new Runnable() { 1945 @Override 1946 public void run() { 1947 callback.onReceiveValue(null); 1948 } 1949 }); 1950 } else { 1951 nativeGenerateMHTML(mNativeAwContents, path, callback); 1952 } 1953 } 1954 1955 /** 1956 * Try to generate a pathname for saving an MHTML archive. This roughly follows WebView's 1957 * autoname logic. 1958 */ 1959 private static String generateArchiveAutoNamePath(String originalUrl, String baseName) { 1960 String name = null; 1961 if (originalUrl != null && !originalUrl.isEmpty()) { 1962 try { 1963 String path = new URL(originalUrl).getPath(); 1964 int lastSlash = path.lastIndexOf('/'); 1965 if (lastSlash > 0) { 1966 name = path.substring(lastSlash + 1); 1967 } else { 1968 name = path; 1969 } 1970 } catch (MalformedURLException e) { 1971 // If it fails parsing the URL, we'll just rely on the default name below. 1972 } 1973 } 1974 1975 if (TextUtils.isEmpty(name)) name = "index"; 1976 1977 String testName = baseName + name + WEB_ARCHIVE_EXTENSION; 1978 if (!new File(testName).exists()) return testName; 1979 1980 for (int i = 1; i < 100; i++) { 1981 testName = baseName + name + "-" + i + WEB_ARCHIVE_EXTENSION; 1982 if (!new File(testName).exists()) return testName; 1983 } 1984 1985 Log.e(TAG, "Unable to auto generate archive name for path: " + baseName); 1986 return null; 1987 } 1988 1989 public void extractSmartClipData(int x, int y, int width, int height) { 1990 mContentViewCore.extractSmartClipData(x, y, width, height); 1991 } 1992 1993 public void setSmartClipDataListener(ContentViewCore.SmartClipDataListener listener) { 1994 mContentViewCore.setSmartClipDataListener(listener); 1995 } 1996 1997 //-------------------------------------------------------------------------------------------- 1998 // Native methods 1999 //-------------------------------------------------------------------------------------------- 2000 2001 private static native long nativeInit(AwBrowserContext browserContext); 2002 private static native void nativeDestroy(long nativeAwContents); 2003 private static native void nativeSetAwDrawSWFunctionTable(int functionTablePointer); 2004 private static native void nativeSetAwDrawGLFunctionTable(int functionTablePointer); 2005 private static native int nativeGetAwDrawGLFunction(); 2006 private static native int nativeGetNativeInstanceCount(); 2007 private static native void nativeSetShouldDownloadFavicons(); 2008 private native void nativeSetJavaPeers(long nativeAwContents, AwContents awContents, 2009 AwWebContentsDelegate webViewWebContentsDelegate, 2010 AwContentsClientBridge contentsClientBridge, 2011 AwContentsIoThreadClient ioThreadClient, 2012 InterceptNavigationDelegate navigationInterceptionDelegate); 2013 private native int nativeGetWebContents(long nativeAwContents); 2014 2015 private native void nativeDocumentHasImages(long nativeAwContents, Message message); 2016 private native void nativeGenerateMHTML( 2017 long nativeAwContents, String path, ValueCallback<String> callback); 2018 2019 private native void nativeAddVisitedLinks(long nativeAwContents, String[] visitedLinks); 2020 private native boolean nativeOnDraw(long nativeAwContents, Canvas canvas, 2021 boolean isHardwareAccelerated, int scrollX, int scrollY, 2022 int clipLeft, int clipTop, int clipRight, int clipBottom); 2023 private native void nativeSetGlobalVisibleRect(long nativeAwContents, int visibleLeft, 2024 int visibleTop, int visibleRight, int visibleBottom); 2025 private native void nativeFindAllAsync(long nativeAwContents, String searchString); 2026 private native void nativeFindNext(long nativeAwContents, boolean forward); 2027 private native void nativeClearMatches(long nativeAwContents); 2028 private native void nativeClearCache(long nativeAwContents, boolean includeDiskFiles); 2029 private native byte[] nativeGetCertificate(long nativeAwContents); 2030 2031 // Coordinates in desity independent pixels. 2032 private native void nativeRequestNewHitTestDataAt(long nativeAwContents, int x, int y); 2033 private native void nativeUpdateLastHitTestData(long nativeAwContents); 2034 2035 private native void nativeOnSizeChanged(long nativeAwContents, int w, int h, int ow, int oh); 2036 private native void nativeScrollTo(long nativeAwContents, int x, int y); 2037 private native void nativeSetViewVisibility(long nativeAwContents, boolean visible); 2038 private native void nativeSetWindowVisibility(long nativeAwContents, boolean visible); 2039 private native void nativeSetIsPaused(long nativeAwContents, boolean paused); 2040 private native void nativeOnAttachedToWindow(long nativeAwContents, int w, int h); 2041 private static native void nativeOnDetachedFromWindow(long nativeAwContents); 2042 private native void nativeSetDipScale(long nativeAwContents, float dipScale); 2043 private native void nativeSetFixedLayoutSize(long nativeAwContents, 2044 int widthDip, int heightDip); 2045 2046 // Returns null if save state fails. 2047 private native byte[] nativeGetOpaqueState(long nativeAwContents); 2048 2049 // Returns false if restore state fails. 2050 private native boolean nativeRestoreFromOpaqueState(long nativeAwContents, byte[] state); 2051 2052 private native int nativeReleasePopupAwContents(long nativeAwContents); 2053 private native void nativeFocusFirstNode(long nativeAwContents); 2054 private native void nativeSetBackgroundColor(long nativeAwContents, int color); 2055 2056 private native int nativeGetAwDrawGLViewContext(long nativeAwContents); 2057 private native long nativeCapturePicture(long nativeAwContents, int width, int height); 2058 private native void nativeEnableOnNewPicture(long nativeAwContents, boolean enabled); 2059 private native void nativeClearView(long nativeAwContents); 2060 private native void nativeSetExtraHeadersForUrl(long nativeAwContents, 2061 String url, String extraHeaders); 2062 2063 private native void nativeInvokeGeolocationCallback( 2064 long nativeAwContents, boolean value, String requestingFrame); 2065 2066 private native void nativeSetJsOnlineProperty(long nativeAwContents, boolean networkUp); 2067 2068 private native void nativeTrimMemory(long nativeAwContents, int level); 2069 2070 private native void nativeCreatePdfExporter(long nativeAwContents, AwPdfExporter awPdfExporter); 2071} 2072