1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.android_webview;
7 import android.annotation.SuppressLint;
8 import android.app.Activity;
9 import android.content.ComponentCallbacks2;
10 import android.content.Context;
11 import android.content.res.Configuration;
12 import android.graphics.Bitmap;
13 import android.graphics.Canvas;
14 import android.graphics.Color;
15 import android.graphics.Paint;
16 import android.graphics.Picture;
17 import android.graphics.Rect;
18 import android.net.Uri;
19 import android.net.http.SslCertificate;
20 import android.os.AsyncTask;
21 import android.os.Build;
22 import android.os.Bundle;
23 import android.os.Message;
24 import android.text.TextUtils;
25 import android.util.Log;
26 import android.view.KeyEvent;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.view.accessibility.AccessibilityEvent;
31 import android.view.accessibility.AccessibilityNodeInfo;
32 import android.view.accessibility.AccessibilityNodeProvider;
33 import android.view.inputmethod.EditorInfo;
34 import android.view.inputmethod.InputConnection;
35 import android.webkit.GeolocationPermissions;
36 import android.webkit.ValueCallback;
37 import android.widget.OverScroller;
39 import com.google.common.annotations.VisibleForTesting;
41 import org.chromium.android_webview.permission.AwPermissionRequest;
42 import org.chromium.base.CalledByNative;
43 import org.chromium.base.JNINamespace;
44 import org.chromium.base.ThreadUtils;
45 import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
46 import org.chromium.components.navigation_interception.NavigationParams;
47 import org.chromium.content.browser.ContentSettings;
48 import org.chromium.content.browser.ContentViewClient;
49 import org.chromium.content.browser.ContentViewCore;
50 import org.chromium.content.browser.ContentViewStatics;
51 import org.chromium.content.browser.LoadUrlParams;
52 import org.chromium.content.browser.NavigationHistory;
53 import org.chromium.content.browser.PageTransitionTypes;
54 import org.chromium.content.common.CleanupReference;
55 import org.chromium.content_public.Referrer;
56 import org.chromium.content_public.browser.GestureStateListener;
57 import org.chromium.ui.base.ActivityWindowAndroid;
58 import org.chromium.ui.base.WindowAndroid;
59 import org.chromium.ui.gfx.DeviceDisplayInfo;
62 import java.lang.annotation.Annotation;
63 import java.net.MalformedURLException;
65 import java.util.HashMap;
66 import java.util.Locale;
68 import java.util.concurrent.Callable;
72 * Exposes the native AwContents class, and together these classes wrap the ContentViewCore
73 * and Browser components that are required to implement Android WebView API. This is the
74 * primary entry point for the WebViewProvider implementation; it holds a 1:1 object
75 * relationship with application WebView instances.
76 * (We define this class independent of the hidden WebViewProvider interfaces, to allow
77 * continuous build & test in the open source SDK-based tree).
79 @JNINamespace("android_webview")
80 public class AwContents {
81 private static final String TAG = "AwContents";
83 private static final String WEB_ARCHIVE_EXTENSION = ".mht";
85 // Used to avoid enabling zooming in / out if resulting zooming will
86 // produce little visible difference.
87 private static final float ZOOM_CONTROLS_EPSILON = 0.007f;
90 * WebKit hit test related data strcutre. These are used to implement
91 * getHitTestResult, requestFocusNodeHref, requestImageRef methods in WebView.
92 * All values should be updated together. The native counterpart is
95 public static class HitTestData {
96 // Used in getHitTestResult.
97 public int hitTestResultType;
98 public String hitTestResultExtraData;
100 // Used in requestFocusNodeHref (all three) and requestImageRef (only imgSrc).
102 public String anchorText;
103 public String imgSrc;
107 * Interface that consumers of {@link AwContents} must implement to allow the proper
108 * dispatching of view methods through the containing view.
110 public interface InternalAccessDelegate extends ContentViewCore.InternalAccessDelegate {
113 * @see View#overScrollBy(int, int, int, int, int, int, int, int, boolean);
115 void overScrollBy(int deltaX, int deltaY,
116 int scrollX, int scrollY,
117 int scrollRangeX, int scrollRangeY,
118 int maxOverScrollX, int maxOverScrollY,
119 boolean isTouchEvent);
122 * @see View#scrollTo(int, int)
124 void super_scrollTo(int scrollX, int scrollY);
127 * @see View#setMeasuredDimension(int, int)
129 void setMeasuredDimension(int measuredWidth, int measuredHeight);
132 * @see View#getScrollBarStyle()
134 int super_getScrollBarStyle();
137 * Requests a callback on the native DrawGL method (see getAwDrawGLFunction)
138 * if called from within onDraw, |canvas| will be non-null and hardware accelerated.
139 * otherwise, |canvas| will be null, and the container view itself will be hardware
140 * accelerated. If |waitForCompletion| is true, this method will not return until
141 * functor has returned.
142 * Should avoid setting |waitForCompletion| when |canvas| is not null.
144 * @return false indicates the GL draw request was not accepted, and the caller
145 * should fallback to the SW path.
147 boolean requestDrawGL(Canvas canvas, boolean waitForCompletion);
151 * Class to facilitate dependency injection. Subclasses by test code to provide mock versions of
152 * certain AwContents dependencies.
154 public static class DependencyFactory {
155 public AwLayoutSizer createLayoutSizer() {
156 return new AwLayoutSizer();
159 public AwScrollOffsetManager createScrollOffsetManager(
160 AwScrollOffsetManager.Delegate delegate, OverScroller overScroller) {
161 return new AwScrollOffsetManager(delegate, overScroller);
165 private long mNativeAwContents;
166 private final AwBrowserContext mBrowserContext;
167 private final ViewGroup mContainerView;
168 private ContentViewCore mContentViewCore;
169 private final AwContentsClient mContentsClient;
170 private final AwContentViewClient mContentViewClient;
171 private final AwContentsClientBridge mContentsClientBridge;
172 private final AwWebContentsDelegate mWebContentsDelegate;
173 private final AwContentsIoThreadClient mIoThreadClient;
174 private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
175 private final InternalAccessDelegate mInternalAccessAdapter;
176 private final AwLayoutSizer mLayoutSizer;
177 private final AwZoomControls mZoomControls;
178 private final AwScrollOffsetManager mScrollOffsetManager;
179 private OverScrollGlow mOverScrollGlow;
180 // This can be accessed on any thread after construction. See AwContentsIoThreadClient.
181 private final AwSettings mSettings;
182 private final ScrollAccessibilityHelper mScrollAccessibilityHelper;
184 private boolean mIsPaused;
185 private boolean mIsViewVisible;
186 private boolean mIsWindowVisible;
187 private boolean mIsAttachedToWindow;
188 private Bitmap mFavicon;
189 private boolean mHasRequestedVisitedHistoryFromClient;
190 // TODO(boliu): This should be in a global context, not per webview.
191 private final double mDIPScale;
193 // The base background color, i.e. not accounting for any CSS body from the current page.
194 private int mBaseBackgroundColor = Color.WHITE;
195 private int mLayerType = View.LAYER_TYPE_NONE;
197 // Must call nativeUpdateLastHitTestData first to update this before use.
198 private final HitTestData mPossiblyStaleHitTestData = new HitTestData();
200 private final DefaultVideoPosterRequestHandler mDefaultVideoPosterRequestHandler;
202 // Bound method for suppling Picture instances to the AwContentsClient. Will be null if the
203 // picture listener API has not yet been enabled, or if it is using invalidation-only mode.
204 private Callable<Picture> mPictureListenerContentProvider;
206 private boolean mContainerViewFocused;
207 private boolean mWindowFocused;
209 // These come from the compositor and are updated synchronously (in contrast to the values in
210 // ContentViewCore, which are updated at end of every frame).
211 private float mPageScaleFactor = 1.0f;
212 private float mMinPageScaleFactor = 1.0f;
213 private float mMaxPageScaleFactor = 1.0f;
214 private float mContentWidthDip;
215 private float mContentHeightDip;
217 private AwAutofillManagerDelegate mAwAutofillManagerDelegate;
219 private ComponentCallbacks2 mComponentCallbacks;
221 private AwPdfExporter mAwPdfExporter;
223 // This flag indicates that ShouldOverrideUrlNavigation should be posted
224 // through the resourcethrottle. This is only used for popup windows.
225 private boolean mDeferredShouldOverrideUrlLoadingIsPendingForPopup;
227 private static final class DestroyRunnable implements Runnable {
228 private final long mNativeAwContents;
229 private DestroyRunnable(long nativeAwContents) {
230 mNativeAwContents = nativeAwContents;
234 nativeDestroy(mNativeAwContents);
238 // Reference to the active mNativeAwContents pointer while it is active use
239 // (ie before it is destroyed).
240 private CleanupReference mCleanupReference;
242 //--------------------------------------------------------------------------------------------
243 private class IoThreadClientImpl implements AwContentsIoThreadClient {
244 // All methods are called on the IO thread.
247 public int getCacheMode() {
248 return mSettings.getCacheMode();
252 public InterceptedRequestData shouldInterceptRequest(final String url,
253 boolean isMainFrame) {
254 InterceptedRequestData interceptedRequestData;
255 // Return the response directly if the url is default video poster url.
256 interceptedRequestData = mDefaultVideoPosterRequestHandler.shouldInterceptRequest(url);
257 if (interceptedRequestData != null) return interceptedRequestData;
259 interceptedRequestData = mContentsClient.shouldInterceptRequest(url);
261 if (interceptedRequestData == null) {
262 mContentsClient.getCallbackHelper().postOnLoadResource(url);
265 if (isMainFrame && interceptedRequestData != null &&
266 interceptedRequestData.getData() == null) {
267 // In this case the intercepted URLRequest job will simulate an empty response
268 // which doesn't trigger the onReceivedError callback. For WebViewClassic
269 // compatibility we synthesize that callback. http://crbug.com/180950
270 mContentsClient.getCallbackHelper().postOnReceivedError(
271 ErrorCodeConversionHelper.ERROR_UNKNOWN,
272 null /* filled in by the glue layer */, url);
274 return interceptedRequestData;
278 public boolean shouldBlockContentUrls() {
279 return !mSettings.getAllowContentAccess();
283 public boolean shouldBlockFileUrls() {
284 return !mSettings.getAllowFileAccess();
288 public boolean shouldBlockNetworkLoads() {
289 return mSettings.getBlockNetworkLoads();
293 public void onDownloadStart(String url, String userAgent,
294 String contentDisposition, String mimeType, long contentLength) {
295 mContentsClient.getCallbackHelper().postOnDownloadStart(url, userAgent,
296 contentDisposition, mimeType, contentLength);
300 public void newLoginRequest(String realm, String account, String args) {
301 mContentsClient.getCallbackHelper().postOnReceivedLoginRequest(realm, account, args);
305 //--------------------------------------------------------------------------------------------
306 // When the navigation is for a newly created WebView (i.e. a popup), intercept the navigation
307 // here for implementing shouldOverrideUrlLoading. This is to send the shouldOverrideUrlLoading
308 // callback to the correct WebViewClient that is associated with the WebView.
309 // Otherwise, use this delegate only to post onPageStarted messages.
311 // We are not using WebContentsObserver.didStartLoading because of stale URLs, out of order
312 // onPageStarted's and double onPageStarted's.
314 private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
316 public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
317 final String url = navigationParams.url;
318 boolean ignoreNavigation = false;
319 if (mDeferredShouldOverrideUrlLoadingIsPendingForPopup) {
320 mDeferredShouldOverrideUrlLoadingIsPendingForPopup = false;
321 // If this is used for all navigations in future, cases for application initiated
322 // load, redirect and backforward should also be filtered out.
323 if (!navigationParams.isPost) {
324 ignoreNavigation = mContentsClient.shouldOverrideUrlLoading(url);
327 // The shouldOverrideUrlLoading call might have resulted in posting messages to the
328 // UI thread. Using sendMessage here (instead of calling onPageStarted directly)
329 // will allow those to run in order.
330 if (!ignoreNavigation) {
331 mContentsClient.getCallbackHelper().postOnPageStarted(url);
333 return ignoreNavigation;
337 //--------------------------------------------------------------------------------------------
338 private class AwLayoutSizerDelegate implements AwLayoutSizer.Delegate {
340 public void requestLayout() {
341 mContainerView.requestLayout();
345 public void setMeasuredDimension(int measuredWidth, int measuredHeight) {
346 mInternalAccessAdapter.setMeasuredDimension(measuredWidth, measuredHeight);
350 public void setFixedLayoutSize(int widthDip, int heightDip) {
351 if (mNativeAwContents == 0) return;
352 nativeSetFixedLayoutSize(mNativeAwContents, widthDip, heightDip);
356 public boolean isLayoutParamsHeightWrapContent() {
357 return mContainerView.getLayoutParams() != null &&
358 mContainerView.getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT;
362 //--------------------------------------------------------------------------------------------
363 private class AwScrollOffsetManagerDelegate implements AwScrollOffsetManager.Delegate {
365 public void overScrollContainerViewBy(int deltaX, int deltaY, int scrollX, int scrollY,
366 int scrollRangeX, int scrollRangeY, boolean isTouchEvent) {
367 mInternalAccessAdapter.overScrollBy(deltaX, deltaY, scrollX, scrollY,
368 scrollRangeX, scrollRangeY, 0, 0, isTouchEvent);
372 public void scrollContainerViewTo(int x, int y) {
373 mInternalAccessAdapter.super_scrollTo(x, y);
377 public void scrollNativeTo(int x, int y) {
378 if (mNativeAwContents == 0) return;
379 nativeScrollTo(mNativeAwContents, x, y);
383 public int getContainerViewScrollX() {
384 return mContainerView.getScrollX();
388 public int getContainerViewScrollY() {
389 return mContainerView.getScrollY();
393 public void invalidate() {
394 mContainerView.invalidate();
398 //--------------------------------------------------------------------------------------------
399 private class AwGestureStateListener extends GestureStateListener {
401 public void onPinchStarted() {
402 // While it's possible to re-layout the view during a pinch gesture, the effect is very
403 // janky (especially that the page scale update notification comes from the renderer
404 // main thread, not from the impl thread, so it's usually out of sync with what's on
405 // screen). It's also quite expensive to do a re-layout, so we simply postpone
406 // re-layout for the duration of the gesture. This is compatible with what
407 // WebViewClassic does.
408 mLayoutSizer.freezeLayoutRequests();
412 public void onPinchEnded() {
413 mLayoutSizer.unfreezeLayoutRequests();
417 public void onFlingCancelGesture() {
418 mScrollOffsetManager.onFlingCancelGesture();
422 public void onUnhandledFlingStartEvent(int velocityX, int velocityY) {
423 mScrollOffsetManager.onUnhandledFlingStartEvent(velocityX, velocityY);
427 public void onScrollUpdateGestureConsumed() {
428 mScrollAccessibilityHelper.postViewScrolledAccessibilityEventCallback();
432 //--------------------------------------------------------------------------------------------
433 private class AwComponentCallbacks implements ComponentCallbacks2 {
435 public void onTrimMemory(final int level) {
436 if (mNativeAwContents == 0) return;
437 boolean visibleRectEmpty = getGlobalVisibleRect().isEmpty();
438 final boolean visible = mIsViewVisible && mIsWindowVisible && !visibleRectEmpty;
439 nativeTrimMemory(mNativeAwContents, level, visible);
443 public void onLowMemory() {}
446 public void onConfigurationChanged(Configuration configuration) {}
449 //--------------------------------------------------------------------------------------------
450 private class AwLayoutChangeListener implements View.OnLayoutChangeListener {
452 public void onLayoutChange(View v, int left, int top, int right, int bottom,
453 int oldLeft, int oldTop, int oldRight, int oldBottom) {
454 assert v == mContainerView;
455 mLayoutSizer.onLayoutChange();
460 * @param browserContext the browsing context to associate this view contents with.
461 * @param containerView the view-hierarchy item this object will be bound to.
462 * @param internalAccessAdapter to access private methods on containerView.
463 * @param contentsClient will receive API callbacks from this WebView Contents.
464 * @param awSettings AwSettings instance used to configure the AwContents.
466 * This constructor uses the default view sizing policy.
468 public AwContents(AwBrowserContext browserContext, ViewGroup containerView,
469 InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient,
470 AwSettings awSettings) {
471 this(browserContext, containerView, internalAccessAdapter, contentsClient, awSettings,
472 new DependencyFactory());
476 * @param dependencyFactory an instance of the DependencyFactory used to provide instances of
477 * classes that this class depends on.
479 * This version of the constructor is used in test code to inject test versions of the above
480 * documented classes.
482 public AwContents(AwBrowserContext browserContext, ViewGroup containerView,
483 InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient,
484 AwSettings settings, DependencyFactory dependencyFactory) {
485 mBrowserContext = browserContext;
486 mContainerView = containerView;
487 mInternalAccessAdapter = internalAccessAdapter;
488 mContentsClient = contentsClient;
489 mContentViewClient = new AwContentViewClient(contentsClient, settings);
490 mLayoutSizer = dependencyFactory.createLayoutSizer();
491 mSettings = settings;
492 mDIPScale = DeviceDisplayInfo.create(mContainerView.getContext()).getDIPScale();
493 mLayoutSizer.setDelegate(new AwLayoutSizerDelegate());
494 mLayoutSizer.setDIPScale(mDIPScale);
495 mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient, mContainerView);
496 mContentsClientBridge = new AwContentsClientBridge(contentsClient,
497 mBrowserContext.getKeyStore(), AwContentsStatics.getClientCertLookupTable());
498 mZoomControls = new AwZoomControls(this);
499 mIoThreadClient = new IoThreadClientImpl();
500 mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
502 AwSettings.ZoomSupportChangeListener zoomListener =
503 new AwSettings.ZoomSupportChangeListener() {
505 public void onGestureZoomSupportChanged(
506 boolean supportsDoubleTapZoom, boolean supportsMultiTouchZoom) {
507 mContentViewCore.updateDoubleTapSupport(supportsDoubleTapZoom);
508 mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoom);
512 mSettings.setZoomListener(zoomListener);
513 mDefaultVideoPosterRequestHandler = new DefaultVideoPosterRequestHandler(mContentsClient);
514 mSettings.setDefaultVideoPosterURL(
515 mDefaultVideoPosterRequestHandler.getDefaultVideoPosterURL());
516 mSettings.setDIPScale(mDIPScale);
517 mScrollOffsetManager = dependencyFactory.createScrollOffsetManager(
518 new AwScrollOffsetManagerDelegate(), new OverScroller(mContainerView.getContext()));
519 mScrollAccessibilityHelper = new ScrollAccessibilityHelper(mContainerView);
521 setOverScrollMode(mContainerView.getOverScrollMode());
522 setScrollBarStyle(mInternalAccessAdapter.super_getScrollBarStyle());
523 mContainerView.addOnLayoutChangeListener(new AwLayoutChangeListener());
525 setNewAwContents(nativeInit(mBrowserContext));
527 onVisibilityChanged(mContainerView, mContainerView.getVisibility());
528 onWindowVisibilityChanged(mContainerView.getWindowVisibility());
531 private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView,
532 InternalAccessDelegate internalDispatcher, long nativeWebContents,
533 GestureStateListener gestureStateListener,
534 ContentViewClient contentViewClient,
535 ContentViewCore.ZoomControlsDelegate zoomControlsDelegate) {
536 Context context = containerView.getContext();
537 ContentViewCore contentViewCore = new ContentViewCore(context);
538 contentViewCore.initialize(containerView, internalDispatcher, nativeWebContents,
539 context instanceof Activity ?
540 new ActivityWindowAndroid((Activity) context) :
541 new WindowAndroid(context.getApplicationContext()));
542 contentViewCore.addGestureStateListener(gestureStateListener);
543 contentViewCore.setContentViewClient(contentViewClient);
544 contentViewCore.setZoomControlsDelegate(zoomControlsDelegate);
545 return contentViewCore;
549 * Common initialization routine for adopting a native AwContents instance into this
552 * TAKE CARE! This method can get called multiple times per java instance. Code accordingly.
553 * ^^^^^^^^^ See the native class declaration for more details on relative object lifetimes.
555 private void setNewAwContents(long newAwContentsPtr) {
556 if (mNativeAwContents != 0) {
558 mContentViewCore = null;
561 assert mNativeAwContents == 0 && mCleanupReference == null && mContentViewCore == null;
563 mNativeAwContents = newAwContentsPtr;
564 // TODO(joth): when the native and java counterparts of AwBrowserContext are hooked up to
565 // each other, we should update |mBrowserContext| according to the newly received native
566 // WebContent's browser context.
568 // The native side object has been bound to this java instance, so now is the time to
569 // bind all the native->java relationships.
570 mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));
572 long nativeWebContents = nativeGetWebContents(mNativeAwContents);
573 mContentViewCore = createAndInitializeContentViewCore(
574 mContainerView, mInternalAccessAdapter, nativeWebContents,
575 new AwGestureStateListener(), mContentViewClient, mZoomControls);
576 nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
577 mIoThreadClient, mInterceptNavigationDelegate);
578 mContentsClient.installWebContentsObserver(mContentViewCore);
579 mSettings.setWebContents(nativeWebContents);
580 nativeSetDipScale(mNativeAwContents, (float) mDIPScale);
582 // The only call to onShow. onHide should never be called.
583 mContentViewCore.onShow();
587 * Called on the "source" AwContents that is opening the popup window to
588 * provide the AwContents to host the pop up content.
590 public void supplyContentsForPopup(AwContents newContents) {
591 long popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents);
592 if (popupNativeAwContents == 0) {
593 Log.w(TAG, "Popup WebView bind failed: no pending content.");
594 if (newContents != null) newContents.destroy();
597 if (newContents == null) {
598 nativeDestroy(popupNativeAwContents);
602 newContents.receivePopupContents(popupNativeAwContents);
605 // Recap: supplyContentsForPopup() is called on the parent window's content, this method is
606 // called on the popup window's content.
607 private void receivePopupContents(long popupNativeAwContents) {
608 mDeferredShouldOverrideUrlLoadingIsPendingForPopup = true;
609 // Save existing view state.
610 final boolean wasAttached = mIsAttachedToWindow;
611 final boolean wasViewVisible = mIsViewVisible;
612 final boolean wasWindowVisible = mIsWindowVisible;
613 final boolean wasPaused = mIsPaused;
614 final boolean wasFocused = mContainerViewFocused;
615 final boolean wasWindowFocused = mWindowFocused;
617 // Properly clean up existing mContentViewCore and mNativeAwContents.
618 if (wasFocused) onFocusChanged(false, 0, null);
619 if (wasWindowFocused) onWindowFocusChanged(false);
620 if (wasViewVisible) setViewVisibilityInternal(false);
621 if (wasWindowVisible) setWindowVisibilityInternal(false);
622 if (!wasPaused) onPause();
623 // Not calling onDetachedFromWindow here because native code requires GL context to release
624 // GL resources. This case is properly handled when destroy is called while still attached
627 setNewAwContents(popupNativeAwContents);
629 // Finally refresh all view state for mContentViewCore and mNativeAwContents.
630 if (!wasPaused) onResume();
631 if (wasAttached) onAttachedToWindow();
632 onSizeChanged(mContainerView.getWidth(), mContainerView.getHeight(), 0, 0);
633 if (wasWindowVisible) setWindowVisibilityInternal(true);
634 if (wasViewVisible) setViewVisibilityInternal(true);
635 if (wasWindowFocused) onWindowFocusChanged(wasWindowFocused);
636 if (wasFocused) onFocusChanged(true, 0, null);
640 * Deletes the native counterpart of this object.
642 public void destroy() {
643 if (mCleanupReference != null) {
644 assert mNativeAwContents != 0;
645 // If we are attached, we have to call native detach to clean up
646 // hardware resources.
647 if (mIsAttachedToWindow) {
648 nativeOnDetachedFromWindow(mNativeAwContents);
651 // We explicitly do not null out the mContentViewCore reference here
652 // because ContentViewCore already has code to deal with the case
653 // methods are called on it after it's been destroyed, and other
654 // code relies on AwContents.mContentViewCore to be non-null.
655 mContentViewCore.destroy();
656 mNativeAwContents = 0;
658 mCleanupReference.cleanupNow();
659 mCleanupReference = null;
662 assert !mContentViewCore.isAlive();
663 assert mNativeAwContents == 0;
667 public ContentViewCore getContentViewCore() {
668 return mContentViewCore;
671 // Can be called from any thread.
672 public AwSettings getSettings() {
676 public AwPdfExporter getPdfExporter() {
677 // mNativeAwContents can be null, due to destroy().
678 if (mNativeAwContents == 0) {
681 if (mAwPdfExporter == null) {
682 mAwPdfExporter = new AwPdfExporter(mContainerView);
683 nativeCreatePdfExporter(mNativeAwContents, mAwPdfExporter);
685 return mAwPdfExporter;
688 public static void setAwDrawSWFunctionTable(long functionTablePointer) {
689 nativeSetAwDrawSWFunctionTable(functionTablePointer);
692 public static void setAwDrawGLFunctionTable(long functionTablePointer) {
693 nativeSetAwDrawGLFunctionTable(functionTablePointer);
696 public static long getAwDrawGLFunction() {
697 return nativeGetAwDrawGLFunction();
700 public static void setShouldDownloadFavicons() {
701 nativeSetShouldDownloadFavicons();
705 * Disables contents of JS-to-Java bridge objects to be inspectable using
706 * Object.keys() method and "for .. in" loops. This is intended for applications
707 * targeting earlier Android releases where this was not possible, and we want
708 * to ensure backwards compatible behavior.
710 public void disableJavascriptInterfacesInspection() {
711 mContentViewCore.setAllowJavascriptInterfacesInspection(false);
715 * Intended for test code.
716 * @return the number of native instances of this class.
719 public static int getNativeInstanceCount() {
720 return nativeGetNativeInstanceCount();
723 public long getAwDrawGLViewContext() {
724 // Only called during early construction, so client should not have had a chance to
726 assert mNativeAwContents != 0;
728 // Using the native pointer as the returned viewContext. This is matched by the
729 // reinterpret_cast back to BrowserViewRenderer pointer in the native DrawGLFunction.
730 return nativeGetAwDrawGLViewContext(mNativeAwContents);
733 // This is only to avoid heap allocations inside getGlobalVisibleRect. It should treated
734 // as a local variable in the function and not used anywhere else.
735 private static final Rect sLocalGlobalVisibleRect = new Rect();
737 private Rect getGlobalVisibleRect() {
738 if (!mContainerView.getGlobalVisibleRect(sLocalGlobalVisibleRect)) {
739 sLocalGlobalVisibleRect.setEmpty();
741 return sLocalGlobalVisibleRect;
744 //--------------------------------------------------------------------------------------------
745 // WebView[Provider] method implementations (where not provided by ContentViewCore)
746 //--------------------------------------------------------------------------------------------
748 // Only valid within onDraw().
749 private final Rect mClipBoundsTemporary = new Rect();
751 public void onDraw(Canvas canvas) {
752 if (mNativeAwContents == 0) {
753 canvas.drawColor(getEffectiveBackgroundColor());
757 mScrollOffsetManager.syncScrollOffsetFromOnDraw();
758 canvas.getClipBounds(mClipBoundsTemporary);
759 Rect globalVisibleRect = getGlobalVisibleRect();
761 if (!nativeOnDraw(mNativeAwContents, canvas, canvas.isHardwareAccelerated(),
762 mContainerView.getScrollX(), mContainerView.getScrollY(),
763 globalVisibleRect.left, globalVisibleRect.top,
764 globalVisibleRect.right, globalVisibleRect.bottom,
765 mClipBoundsTemporary.left, mClipBoundsTemporary.top,
766 mClipBoundsTemporary.right, mClipBoundsTemporary.bottom)) {
767 // Can happen during initialization when compositor is not set up. Or when clearView
768 // is in effect. Just draw background color instead.
769 canvas.drawColor(getEffectiveBackgroundColor());
772 if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas,
773 mScrollOffsetManager.computeMaximumHorizontalScrollOffset(),
774 mScrollOffsetManager.computeMaximumVerticalScrollOffset())) {
775 mContainerView.invalidate();
779 public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
780 mLayoutSizer.onMeasure(widthMeasureSpec, heightMeasureSpec);
783 public int getContentHeightCss() {
784 return (int) Math.ceil(mContentHeightDip);
787 public int getContentWidthCss() {
788 return (int) Math.ceil(mContentWidthDip);
791 public Picture capturePicture() {
792 if (mNativeAwContents == 0) return null;
793 return new AwPicture(nativeCapturePicture(mNativeAwContents,
794 mScrollOffsetManager.computeHorizontalScrollRange(),
795 mScrollOffsetManager.computeVerticalScrollRange()));
798 public void clearView() {
799 if (mNativeAwContents == 0) return;
800 nativeClearView(mNativeAwContents);
804 * Enable the onNewPicture callback.
805 * @param enabled Flag to enable the callback.
806 * @param invalidationOnly Flag to call back only on invalidation without providing a picture.
808 public void enableOnNewPicture(boolean enabled, boolean invalidationOnly) {
809 if (mNativeAwContents == 0) return;
810 if (invalidationOnly) {
811 mPictureListenerContentProvider = null;
812 } else if (enabled && mPictureListenerContentProvider == null) {
813 mPictureListenerContentProvider = new Callable<Picture>() {
815 public Picture call() {
816 return capturePicture();
820 nativeEnableOnNewPicture(mNativeAwContents, enabled);
823 public void findAllAsync(String searchString) {
824 if (mNativeAwContents == 0) return;
825 nativeFindAllAsync(mNativeAwContents, searchString);
828 public void findNext(boolean forward) {
829 if (mNativeAwContents == 0) return;
830 nativeFindNext(mNativeAwContents, forward);
833 public void clearMatches() {
834 if (mNativeAwContents == 0) return;
835 nativeClearMatches(mNativeAwContents);
839 * @return load progress of the WebContents.
841 public int getMostRecentProgress() {
842 // WebContentsDelegateAndroid conveniently caches the most recent notified value for us.
843 return mWebContentsDelegate.getMostRecentProgress();
846 public Bitmap getFavicon() {
850 private void requestVisitedHistoryFromClient() {
851 ValueCallback<String[]> callback = new ValueCallback<String[]>() {
853 public void onReceiveValue(final String[] value) {
854 ThreadUtils.runOnUiThread(new Runnable() {
857 if (mNativeAwContents == 0) return;
858 nativeAddVisitedLinks(mNativeAwContents, value);
863 mContentsClient.getVisitedHistory(callback);
867 * Load url without fixing up the url string. Consumers of ContentView are responsible for
868 * ensuring the URL passed in is properly formatted (i.e. the scheme has been added if left
869 * off during user input).
871 * @param params Parameters for this load.
873 public void loadUrl(LoadUrlParams params) {
874 if (params.getLoadUrlType() == LoadUrlParams.LOAD_TYPE_DATA &&
875 !params.isBaseUrlDataScheme()) {
876 // This allows data URLs with a non-data base URL access to file:///android_asset/ and
877 // file:///android_res/ URLs. If AwSettings.getAllowFileAccess permits, it will also
878 // allow access to file:// URLs (subject to OS level permission checks).
879 params.setCanLoadLocalResources(true);
882 // If we are reloading the same url, then set transition type as reload.
883 if (params.getUrl() != null &&
884 params.getUrl().equals(mContentViewCore.getUrl()) &&
885 params.getTransitionType() == PageTransitionTypes.PAGE_TRANSITION_LINK) {
886 params.setTransitionType(PageTransitionTypes.PAGE_TRANSITION_RELOAD);
888 params.setTransitionType(
889 params.getTransitionType() | PageTransitionTypes.PAGE_TRANSITION_FROM_API);
891 // For WebView, always use the user agent override, which is set
892 // every time the user agent in AwSettings is modified.
893 params.setOverrideUserAgent(LoadUrlParams.UA_OVERRIDE_TRUE);
896 // We don't pass extra headers to the content layer, as WebViewClassic
897 // was adding them in a very narrow set of conditions. See http://crbug.com/306873
898 // However, if the embedder is attempting to inject a Referer header for their
899 // loadUrl call, then we set that separately and remove it from the extra headers map/
900 final String REFERER = "referer";
901 Map<String, String> extraHeaders = params.getExtraHeaders();
902 if (extraHeaders != null) {
903 for (String header : extraHeaders.keySet()) {
904 if (REFERER.equals(header.toLowerCase(Locale.US))) {
905 params.setReferrer(new Referrer(extraHeaders.remove(header), 1));
906 params.setExtraHeaders(extraHeaders);
912 if (mNativeAwContents != 0) {
913 nativeSetExtraHeadersForUrl(
914 mNativeAwContents, params.getUrl(), params.getExtraHttpRequestHeadersString());
916 params.setExtraHeaders(new HashMap<String, String>());
918 mContentViewCore.loadUrl(params);
920 // The behavior of WebViewClassic uses the populateVisitedLinks callback in WebKit.
921 // Chromium does not use this use code path and the best emulation of this behavior to call
922 // request visited links once on the first URL load of the WebView.
923 if (!mHasRequestedVisitedHistoryFromClient) {
924 mHasRequestedVisitedHistoryFromClient = true;
925 requestVisitedHistoryFromClient();
928 if (params.getLoadUrlType() == LoadUrlParams.LOAD_TYPE_DATA &&
929 params.getBaseUrl() != null) {
930 // Data loads with a base url will be resolved in Blink, and not cause an onPageStarted
931 // event to be sent. Sending the callback directly from here.
932 mContentsClient.getCallbackHelper().postOnPageStarted(params.getBaseUrl());
937 * Get the URL of the current page.
939 * @return The URL of the current page or null if it's empty.
941 public String getUrl() {
942 String url = mContentViewCore.getUrl();
943 if (url == null || url.trim().isEmpty()) return null;
947 public void requestFocus() {
948 if (mNativeAwContents == 0) return;
949 if (!mContainerView.isInTouchMode() && mSettings.shouldFocusFirstNode()) {
950 nativeFocusFirstNode(mNativeAwContents);
954 public void setBackgroundColor(int color) {
955 mBaseBackgroundColor = color;
956 if (mNativeAwContents != 0) nativeSetBackgroundColor(mNativeAwContents, color);
960 * @see android.view.View#setLayerType()
962 public void setLayerType(int layerType, Paint paint) {
963 mLayerType = layerType;
964 updateHardwareAcceleratedFeaturesToggle();
967 private void updateHardwareAcceleratedFeaturesToggle() {
968 mSettings.setEnableSupportedHardwareAcceleratedFeatures(
969 mIsAttachedToWindow && mContainerView.isHardwareAccelerated() &&
970 (mLayerType == View.LAYER_TYPE_NONE || mLayerType == View.LAYER_TYPE_HARDWARE));
974 private int getEffectiveBackgroundColor() {
975 // Do not ask the ContentViewCore for the background color, as it will always
976 // report white prior to initial navigation or post destruction, whereas we want
977 // to use the client supplied base value in those cases.
978 if (mNativeAwContents == 0 || !mContentsClient.isCachedRendererBackgroundColorValid()) {
979 return mBaseBackgroundColor;
981 return mContentsClient.getCachedRendererBackgroundColor();
984 public boolean isMultiTouchZoomSupported() {
985 return mSettings.supportsMultiTouchZoom();
988 public View getZoomControlsForTest() {
989 return mZoomControls.getZoomControlsViewForTest();
993 * @see ContentViewCore#getContentSettings()
995 public ContentSettings getContentSettings() {
996 return mContentViewCore.getContentSettings();
1000 * @see View#setOverScrollMode(int)
1002 public void setOverScrollMode(int mode) {
1003 if (mode != View.OVER_SCROLL_NEVER) {
1004 mOverScrollGlow = new OverScrollGlow(mContainerView);
1006 mOverScrollGlow = null;
1010 // TODO(mkosiba): In WebViewClassic these appear in some of the scroll extent calculation
1011 // methods but toggling them has no visiual effect on the content (in other words the scrolling
1012 // code behaves as if the scrollbar-related padding is in place but the onDraw code doesn't
1013 // take that into consideration).
1014 // http://crbug.com/269032
1015 private boolean mOverlayHorizontalScrollbar = true;
1016 private boolean mOverlayVerticalScrollbar = false;
1019 * @see View#setScrollBarStyle(int)
1021 public void setScrollBarStyle(int style) {
1022 if (style == View.SCROLLBARS_INSIDE_OVERLAY
1023 || style == View.SCROLLBARS_OUTSIDE_OVERLAY) {
1024 mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
1026 mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
1031 * @see View#setHorizontalScrollbarOverlay(boolean)
1033 public void setHorizontalScrollbarOverlay(boolean overlay) {
1034 mOverlayHorizontalScrollbar = overlay;
1038 * @see View#setVerticalScrollbarOverlay(boolean)
1040 public void setVerticalScrollbarOverlay(boolean overlay) {
1041 mOverlayVerticalScrollbar = overlay;
1045 * @see View#overlayHorizontalScrollbar()
1047 public boolean overlayHorizontalScrollbar() {
1048 return mOverlayHorizontalScrollbar;
1052 * @see View#overlayVerticalScrollbar()
1054 public boolean overlayVerticalScrollbar() {
1055 return mOverlayVerticalScrollbar;
1059 * Called by the embedder when the scroll offset of the containing view has changed.
1060 * @see View#onScrollChanged(int,int)
1062 public void onContainerViewScrollChanged(int l, int t, int oldl, int oldt) {
1063 // A side-effect of View.onScrollChanged is that the scroll accessibility event being sent
1064 // by the base class implementation. This is completely hidden from the base classes and
1065 // cannot be prevented, which is why we need the code below.
1066 mScrollAccessibilityHelper.removePostedViewScrolledAccessibilityEventCallback();
1067 mScrollOffsetManager.onContainerViewScrollChanged(l, t);
1071 * Called by the embedder when the containing view is to be scrolled or overscrolled.
1072 * @see View#onOverScrolled(int,int,int,int)
1074 public void onContainerViewOverScrolled(int scrollX, int scrollY, boolean clampedX,
1076 int oldX = mContainerView.getScrollX();
1077 int oldY = mContainerView.getScrollY();
1079 mScrollOffsetManager.onContainerViewOverScrolled(scrollX, scrollY, clampedX, clampedY);
1081 if (mOverScrollGlow != null) {
1082 mOverScrollGlow.pullGlow(mContainerView.getScrollX(), mContainerView.getScrollY(),
1084 mScrollOffsetManager.computeMaximumHorizontalScrollOffset(),
1085 mScrollOffsetManager.computeMaximumVerticalScrollOffset());
1090 * @see android.webkit.WebView#requestChildRectangleOnScreen(View, Rect, boolean)
1092 public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
1093 return mScrollOffsetManager.requestChildRectangleOnScreen(
1094 child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY(),
1099 * @see View.computeScroll()
1101 public void computeScroll() {
1102 mScrollOffsetManager.computeScrollAndAbsorbGlow(mOverScrollGlow);
1106 * @see View#computeHorizontalScrollRange()
1108 public int computeHorizontalScrollRange() {
1109 return mScrollOffsetManager.computeHorizontalScrollRange();
1113 * @see View#computeHorizontalScrollOffset()
1115 public int computeHorizontalScrollOffset() {
1116 return mScrollOffsetManager.computeHorizontalScrollOffset();
1120 * @see View#computeVerticalScrollRange()
1122 public int computeVerticalScrollRange() {
1123 return mScrollOffsetManager.computeVerticalScrollRange();
1127 * @see View#computeVerticalScrollOffset()
1129 public int computeVerticalScrollOffset() {
1130 return mScrollOffsetManager.computeVerticalScrollOffset();
1134 * @see View#computeVerticalScrollExtent()
1136 public int computeVerticalScrollExtent() {
1137 return mScrollOffsetManager.computeVerticalScrollExtent();
1141 * @see android.webkit.WebView#stopLoading()
1143 public void stopLoading() {
1144 mContentViewCore.stopLoading();
1148 * @see android.webkit.WebView#reload()
1150 public void reload() {
1151 mContentViewCore.reload(true);
1155 * @see android.webkit.WebView#canGoBack()
1157 public boolean canGoBack() {
1158 return mContentViewCore.canGoBack();
1162 * @see android.webkit.WebView#goBack()
1164 public void goBack() {
1165 mContentViewCore.goBack();
1169 * @see android.webkit.WebView#canGoForward()
1171 public boolean canGoForward() {
1172 return mContentViewCore.canGoForward();
1176 * @see android.webkit.WebView#goForward()
1178 public void goForward() {
1179 mContentViewCore.goForward();
1183 * @see android.webkit.WebView#canGoBackOrForward(int)
1185 public boolean canGoBackOrForward(int steps) {
1186 return mContentViewCore.canGoToOffset(steps);
1190 * @see android.webkit.WebView#goBackOrForward(int)
1192 public void goBackOrForward(int steps) {
1193 mContentViewCore.goToOffset(steps);
1197 * @see android.webkit.WebView#pauseTimers()
1199 public void pauseTimers() {
1200 ContentViewStatics.setWebKitSharedTimersSuspended(true);
1204 * @see android.webkit.WebView#resumeTimers()
1206 public void resumeTimers() {
1207 ContentViewStatics.setWebKitSharedTimersSuspended(false);
1211 * @see android.webkit.WebView#onPause()
1213 public void onPause() {
1214 if (mIsPaused || mNativeAwContents == 0) return;
1216 nativeSetIsPaused(mNativeAwContents, mIsPaused);
1220 * @see android.webkit.WebView#onResume()
1222 public void onResume() {
1223 if (!mIsPaused || mNativeAwContents == 0) return;
1225 nativeSetIsPaused(mNativeAwContents, mIsPaused);
1229 * @see android.webkit.WebView#isPaused()
1231 public boolean isPaused() {
1236 * @see android.webkit.WebView#onCreateInputConnection(EditorInfo)
1238 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
1239 return mContentViewCore.onCreateInputConnection(outAttrs);
1243 * @see android.webkit.WebView#onKeyUp(int, KeyEvent)
1245 public boolean onKeyUp(int keyCode, KeyEvent event) {
1246 return mContentViewCore.onKeyUp(keyCode, event);
1249 private boolean isDpadEvent(KeyEvent event) {
1250 if (event.getAction() == KeyEvent.ACTION_DOWN) {
1251 switch (event.getKeyCode()) {
1252 case KeyEvent.KEYCODE_DPAD_CENTER:
1253 case KeyEvent.KEYCODE_DPAD_DOWN:
1254 case KeyEvent.KEYCODE_DPAD_UP:
1255 case KeyEvent.KEYCODE_DPAD_LEFT:
1256 case KeyEvent.KEYCODE_DPAD_RIGHT:
1264 * @see android.webkit.WebView#dispatchKeyEvent(KeyEvent)
1266 public boolean dispatchKeyEvent(KeyEvent event) {
1267 if (isDpadEvent(event)) {
1268 mSettings.setSpatialNavigationEnabled(true);
1270 return mContentViewCore.dispatchKeyEvent(event);
1274 * Clears the resource cache. Note that the cache is per-application, so this will clear the
1275 * cache for all WebViews used.
1277 * @param includeDiskFiles if false, only the RAM cache is cleared
1279 public void clearCache(boolean includeDiskFiles) {
1280 if (mNativeAwContents == 0) return;
1281 nativeClearCache(mNativeAwContents, includeDiskFiles);
1284 public void documentHasImages(Message message) {
1285 if (mNativeAwContents == 0) return;
1286 nativeDocumentHasImages(mNativeAwContents, message);
1289 public void saveWebArchive(
1290 final String basename, boolean autoname, final ValueCallback<String> callback) {
1292 saveWebArchiveInternal(basename, callback);
1295 // If auto-generating the file name, handle the name generation on a background thread
1296 // as it will require I/O access for checking whether previous files existed.
1297 new AsyncTask<Void, Void, String>() {
1299 protected String doInBackground(Void... params) {
1300 return generateArchiveAutoNamePath(getOriginalUrl(), basename);
1304 protected void onPostExecute(String result) {
1305 saveWebArchiveInternal(result, callback);
1310 public String getOriginalUrl() {
1311 NavigationHistory history = mContentViewCore.getNavigationHistory();
1312 int currentIndex = history.getCurrentEntryIndex();
1313 if (currentIndex >= 0 && currentIndex < history.getEntryCount()) {
1314 return history.getEntryAtIndex(currentIndex).getOriginalUrl();
1320 * @see ContentViewCore#getNavigationHistory()
1322 public NavigationHistory getNavigationHistory() {
1323 return mContentViewCore.getNavigationHistory();
1327 * @see android.webkit.WebView#getTitle()
1329 public String getTitle() {
1330 return mContentViewCore.getTitle();
1334 * @see android.webkit.WebView#clearHistory()
1336 public void clearHistory() {
1337 mContentViewCore.clearHistory();
1340 public String[] getHttpAuthUsernamePassword(String host, String realm) {
1341 return mBrowserContext.getHttpAuthDatabase(mContentViewCore.getContext())
1342 .getHttpAuthUsernamePassword(host, realm);
1345 public void setHttpAuthUsernamePassword(String host, String realm, String username,
1347 mBrowserContext.getHttpAuthDatabase(mContentViewCore.getContext())
1348 .setHttpAuthUsernamePassword(host, realm, username, password);
1352 * @see android.webkit.WebView#getCertificate()
1354 public SslCertificate getCertificate() {
1355 if (mNativeAwContents == 0) return null;
1356 return SslUtil.getCertificateFromDerBytes(nativeGetCertificate(mNativeAwContents));
1360 * @see android.webkit.WebView#clearSslPreferences()
1362 public void clearSslPreferences() {
1363 mContentViewCore.clearSslPreferences();
1366 // TODO(sgurun) remove after this rolls in. To keep internal tree happy.
1367 public void clearClientCertPreferences() { }
1370 * Method to return all hit test values relevant to public WebView API.
1371 * Note that this expose more data than needed for WebView.getHitTestResult.
1372 * Unsafely returning reference to mutable internal object to avoid excessive
1373 * garbage allocation on repeated calls.
1375 public HitTestData getLastHitTestResult() {
1376 if (mNativeAwContents == 0) return null;
1377 nativeUpdateLastHitTestData(mNativeAwContents);
1378 return mPossiblyStaleHitTestData;
1382 * @see android.webkit.WebView#requestFocusNodeHref()
1384 public void requestFocusNodeHref(Message msg) {
1385 if (msg == null || mNativeAwContents == 0) return;
1387 nativeUpdateLastHitTestData(mNativeAwContents);
1388 Bundle data = msg.getData();
1390 // In order to maintain compatibility with the old WebView's implementation,
1391 // the absolute (full) url is passed in the |url| field, not only the href attribute.
1392 // Note: HitTestData could be cleaned up at this point. See http://crbug.com/290992.
1393 data.putString("url", mPossiblyStaleHitTestData.href);
1394 data.putString("title", mPossiblyStaleHitTestData.anchorText);
1395 data.putString("src", mPossiblyStaleHitTestData.imgSrc);
1401 * @see android.webkit.WebView#requestImageRef()
1403 public void requestImageRef(Message msg) {
1404 if (msg == null || mNativeAwContents == 0) return;
1406 nativeUpdateLastHitTestData(mNativeAwContents);
1407 Bundle data = msg.getData();
1408 data.putString("url", mPossiblyStaleHitTestData.imgSrc);
1414 public float getPageScaleFactor() {
1415 return mPageScaleFactor;
1419 * @see android.webkit.WebView#getScale()
1421 * Please note that the scale returned is the page scale multiplied by
1422 * the screen density factor. See CTS WebViewTest.testSetInitialScale.
1424 public float getScale() {
1425 return (float)(mPageScaleFactor * mDIPScale);
1429 * @see android.webkit.WebView#flingScroll(int, int)
1431 public void flingScroll(int velocityX, int velocityY) {
1432 mScrollOffsetManager.flingScroll(velocityX, velocityY);
1436 * @see android.webkit.WebView#pageUp(boolean)
1438 public boolean pageUp(boolean top) {
1439 return mScrollOffsetManager.pageUp(top);
1443 * @see android.webkit.WebView#pageDown(boolean)
1445 public boolean pageDown(boolean bottom) {
1446 return mScrollOffsetManager.pageDown(bottom);
1450 * @see android.webkit.WebView#canZoomIn()
1452 // This method uses the term 'zoom' for legacy reasons, but relates
1453 // to what chrome calls the 'page scale factor'.
1454 public boolean canZoomIn() {
1455 final float zoomInExtent = mMaxPageScaleFactor - mPageScaleFactor;
1456 return zoomInExtent > ZOOM_CONTROLS_EPSILON;
1460 * @see android.webkit.WebView#canZoomOut()
1462 // This method uses the term 'zoom' for legacy reasons, but relates
1463 // to what chrome calls the 'page scale factor'.
1464 public boolean canZoomOut() {
1465 final float zoomOutExtent = mPageScaleFactor - mMinPageScaleFactor;
1466 return zoomOutExtent > ZOOM_CONTROLS_EPSILON;
1470 * @see android.webkit.WebView#zoomIn()
1472 // This method uses the term 'zoom' for legacy reasons, but relates
1473 // to what chrome calls the 'page scale factor'.
1474 public boolean zoomIn() {
1478 return mContentViewCore.pinchByDelta(1.25f);
1482 * @see android.webkit.WebView#zoomOut()
1484 // This method uses the term 'zoom' for legacy reasons, but relates
1485 // to what chrome calls the 'page scale factor'.
1486 public boolean zoomOut() {
1487 if (!canZoomOut()) {
1490 return mContentViewCore.pinchByDelta(0.8f);
1494 * @see android.webkit.WebView#invokeZoomPicker()
1496 public void invokeZoomPicker() {
1497 mContentViewCore.invokeZoomPicker();
1501 * @see android.webkit.WebView#preauthorizePermission(Uri, long)
1503 public void preauthorizePermission(Uri origin, long resources) {
1504 if (mNativeAwContents == 0) return;
1505 nativePreauthorizePermission(mNativeAwContents, origin.toString(), resources);
1509 * @see ContentViewCore.evaluateJavaScript(String, ContentViewCore.JavaScriptCallback)
1511 public void evaluateJavaScript(String script, final ValueCallback<String> callback) {
1512 ContentViewCore.JavaScriptCallback jsCallback = null;
1513 if (callback != null) {
1514 jsCallback = new ContentViewCore.JavaScriptCallback() {
1516 public void handleJavaScriptResult(String jsonResult) {
1517 callback.onReceiveValue(jsonResult);
1522 mContentViewCore.evaluateJavaScript(script, jsCallback);
1526 * @see ContentViewCore.evaluateJavaScriptEvenIfNotYetNavigated(String)
1528 public void evaluateJavaScriptEvenIfNotYetNavigated(String script) {
1529 mContentViewCore.evaluateJavaScriptEvenIfNotYetNavigated(script);
1532 //--------------------------------------------------------------------------------------------
1533 // View and ViewGroup method implementations
1534 //--------------------------------------------------------------------------------------------
1537 * @see android.webkit.View#onTouchEvent()
1539 public boolean onTouchEvent(MotionEvent event) {
1540 if (mNativeAwContents == 0) return false;
1542 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
1543 mSettings.setSpatialNavigationEnabled(false);
1546 mScrollOffsetManager.setProcessingTouchEvent(true);
1547 boolean rv = mContentViewCore.onTouchEvent(event);
1548 mScrollOffsetManager.setProcessingTouchEvent(false);
1550 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
1551 int actionIndex = event.getActionIndex();
1553 // Note this will trigger IPC back to browser even if nothing is hit.
1554 nativeRequestNewHitTestDataAt(mNativeAwContents,
1555 (int) Math.round(event.getX(actionIndex) / mDIPScale),
1556 (int) Math.round(event.getY(actionIndex) / mDIPScale));
1559 if (mOverScrollGlow != null && event.getActionMasked() == MotionEvent.ACTION_UP) {
1560 mOverScrollGlow.releaseAll();
1567 * @see android.view.View#onHoverEvent()
1569 public boolean onHoverEvent(MotionEvent event) {
1570 return mContentViewCore.onHoverEvent(event);
1574 * @see android.view.View#onGenericMotionEvent()
1576 public boolean onGenericMotionEvent(MotionEvent event) {
1577 return mContentViewCore.onGenericMotionEvent(event);
1581 * @see android.view.View#onConfigurationChanged()
1583 public void onConfigurationChanged(Configuration newConfig) {
1584 mContentViewCore.onConfigurationChanged(newConfig);
1588 * @see android.view.View#onAttachedToWindow()
1590 * Note that this is also called from receivePopupContents.
1592 public void onAttachedToWindow() {
1593 if (mNativeAwContents == 0) return;
1594 if (mIsAttachedToWindow) {
1595 Log.w(TAG, "onAttachedToWindow called when already attached. Ignoring");
1598 mIsAttachedToWindow = true;
1600 mContentViewCore.onAttachedToWindow();
1601 nativeOnAttachedToWindow(mNativeAwContents, mContainerView.getWidth(),
1602 mContainerView.getHeight());
1603 updateHardwareAcceleratedFeaturesToggle();
1605 if (mComponentCallbacks != null) return;
1606 mComponentCallbacks = new AwComponentCallbacks();
1607 mContainerView.getContext().registerComponentCallbacks(mComponentCallbacks);
1611 * @see android.view.View#onDetachedFromWindow()
1613 @SuppressLint("MissingSuperCall")
1614 public void onDetachedFromWindow() {
1615 if (!mIsAttachedToWindow) {
1616 Log.w(TAG, "onDetachedFromWindow called when already detached. Ignoring");
1619 mIsAttachedToWindow = false;
1620 hideAutofillPopup();
1621 if (mNativeAwContents != 0) {
1622 nativeOnDetachedFromWindow(mNativeAwContents);
1625 mContentViewCore.onDetachedFromWindow();
1626 updateHardwareAcceleratedFeaturesToggle();
1628 if (mComponentCallbacks != null) {
1629 mContainerView.getContext().unregisterComponentCallbacks(mComponentCallbacks);
1630 mComponentCallbacks = null;
1633 mScrollAccessibilityHelper.removePostedCallbacks();
1637 * @see android.view.View#onWindowFocusChanged()
1639 public void onWindowFocusChanged(boolean hasWindowFocus) {
1640 mWindowFocused = hasWindowFocus;
1641 mContentViewCore.onWindowFocusChanged(hasWindowFocus);
1645 * @see android.view.View#onFocusChanged()
1647 public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
1648 mContainerViewFocused = focused;
1649 mContentViewCore.onFocusChanged(focused);
1653 * @see android.view.View#onSizeChanged()
1655 public void onSizeChanged(int w, int h, int ow, int oh) {
1656 if (mNativeAwContents == 0) return;
1657 mScrollOffsetManager.setContainerViewSize(w, h);
1658 // The AwLayoutSizer needs to go first so that if we're in fixedLayoutSize mode the update
1659 // to enter fixedLayoutSize mode is sent before the first resize update.
1660 mLayoutSizer.onSizeChanged(w, h, ow, oh);
1661 mContentViewCore.onPhysicalBackingSizeChanged(w, h);
1662 mContentViewCore.onSizeChanged(w, h, ow, oh);
1663 nativeOnSizeChanged(mNativeAwContents, w, h, ow, oh);
1667 * @see android.view.View#onVisibilityChanged()
1669 public void onVisibilityChanged(View changedView, int visibility) {
1670 boolean viewVisible = mContainerView.getVisibility() == View.VISIBLE;
1671 if (mIsViewVisible == viewVisible) return;
1672 setViewVisibilityInternal(viewVisible);
1676 * @see android.view.View#onWindowVisibilityChanged()
1678 public void onWindowVisibilityChanged(int visibility) {
1679 boolean windowVisible = visibility == View.VISIBLE;
1680 if (mIsWindowVisible == windowVisible) return;
1681 setWindowVisibilityInternal(windowVisible);
1684 private void setViewVisibilityInternal(boolean visible) {
1685 mIsViewVisible = visible;
1686 if (mNativeAwContents == 0) return;
1687 nativeSetViewVisibility(mNativeAwContents, mIsViewVisible);
1690 private void setWindowVisibilityInternal(boolean visible) {
1691 mIsWindowVisible = visible;
1692 if (mNativeAwContents == 0) return;
1693 nativeSetWindowVisibility(mNativeAwContents, mIsWindowVisible);
1697 * Key for opaque state in bundle. Note this is only public for tests.
1699 public static final String SAVE_RESTORE_STATE_KEY = "WEBVIEW_CHROMIUM_STATE";
1702 * Save the state of this AwContents into provided Bundle.
1703 * @return False if saving state failed.
1705 public boolean saveState(Bundle outState) {
1706 if (mNativeAwContents == 0 || outState == null) return false;
1708 byte[] state = nativeGetOpaqueState(mNativeAwContents);
1709 if (state == null) return false;
1711 outState.putByteArray(SAVE_RESTORE_STATE_KEY, state);
1716 * Restore the state of this AwContents into provided Bundle.
1717 * @param inState Must be a bundle returned by saveState.
1718 * @return False if restoring state failed.
1720 public boolean restoreState(Bundle inState) {
1721 if (mNativeAwContents == 0 || inState == null) return false;
1723 byte[] state = inState.getByteArray(SAVE_RESTORE_STATE_KEY);
1724 if (state == null) return false;
1726 boolean result = nativeRestoreFromOpaqueState(mNativeAwContents, state);
1728 // The onUpdateTitle callback normally happens when a page is loaded,
1729 // but is optimized out in the restoreState case because the title is
1730 // already restored. See WebContentsImpl::UpdateTitleForEntry. So we
1731 // call the callback explicitly here.
1732 if (result) mContentsClient.onReceivedTitle(mContentViewCore.getTitle());
1738 * @see ContentViewCore#addPossiblyUnsafeJavascriptInterface(Object, String, Class)
1740 public void addPossiblyUnsafeJavascriptInterface(Object object, String name,
1741 Class<? extends Annotation> requiredAnnotation) {
1742 mContentViewCore.addPossiblyUnsafeJavascriptInterface(object, name, requiredAnnotation);
1746 * @see android.webkit.WebView#removeJavascriptInterface(String)
1748 public void removeJavascriptInterface(String interfaceName) {
1749 mContentViewCore.removeJavascriptInterface(interfaceName);
1753 * If native accessibility (not script injection) is enabled, and if this is
1754 * running on JellyBean or later, returns an AccessibilityNodeProvider that
1755 * implements native accessibility for this view. Returns null otherwise.
1756 * @return The AccessibilityNodeProvider, if available, or null otherwise.
1758 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
1759 return mContentViewCore.getAccessibilityNodeProvider();
1763 * @see android.webkit.WebView#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
1765 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
1766 mContentViewCore.onInitializeAccessibilityNodeInfo(info);
1770 * @see android.webkit.WebView#onInitializeAccessibilityEvent(AccessibilityEvent)
1772 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
1773 mContentViewCore.onInitializeAccessibilityEvent(event);
1776 public boolean supportsAccessibilityAction(int action) {
1777 return mContentViewCore.supportsAccessibilityAction(action);
1781 * @see android.webkit.WebView#performAccessibilityAction(int, Bundle)
1783 public boolean performAccessibilityAction(int action, Bundle arguments) {
1784 return mContentViewCore.performAccessibilityAction(action, arguments);
1788 * @see android.webkit.WebView#clearFormData()
1790 public void hideAutofillPopup() {
1791 if (mAwAutofillManagerDelegate != null) {
1792 mAwAutofillManagerDelegate.hideAutofillPopup();
1796 public void setNetworkAvailable(boolean networkUp) {
1797 if (mNativeAwContents == 0) return;
1798 nativeSetJsOnlineProperty(mNativeAwContents, networkUp);
1801 //--------------------------------------------------------------------------------------------
1802 // Methods called from native via JNI
1803 //--------------------------------------------------------------------------------------------
1806 private static void onDocumentHasImagesResponse(boolean result, Message message) {
1807 message.arg1 = result ? 1 : 0;
1808 message.sendToTarget();
1812 private void onReceivedTouchIconUrl(String url, boolean precomposed) {
1813 mContentsClient.onReceivedTouchIconUrl(url, precomposed);
1817 private void onReceivedIcon(Bitmap bitmap) {
1818 mContentsClient.onReceivedIcon(bitmap);
1822 /** Callback for generateMHTML. */
1824 private static void generateMHTMLCallback(
1825 String path, long size, ValueCallback<String> callback) {
1826 if (callback == null) return;
1827 callback.onReceiveValue(size < 0 ? null : path);
1831 private void onReceivedHttpAuthRequest(AwHttpAuthHandler handler, String host, String realm) {
1832 mContentsClient.onReceivedHttpAuthRequest(handler, host, realm);
1835 private class AwGeolocationCallback implements GeolocationPermissions.Callback {
1838 public void invoke(final String origin, final boolean allow, final boolean retain) {
1839 ThreadUtils.runOnUiThread(new Runnable() {
1844 mBrowserContext.getGeolocationPermissions().allow(origin);
1846 mBrowserContext.getGeolocationPermissions().deny(origin);
1849 if (mNativeAwContents == 0) return;
1850 nativeInvokeGeolocationCallback(mNativeAwContents, allow, origin);
1857 private void onGeolocationPermissionsShowPrompt(String origin) {
1858 if (mNativeAwContents == 0) return;
1859 AwGeolocationPermissions permissions = mBrowserContext.getGeolocationPermissions();
1860 // Reject if geoloaction is disabled, or the origin has a retained deny
1861 if (!mSettings.getGeolocationEnabled()) {
1862 nativeInvokeGeolocationCallback(mNativeAwContents, false, origin);
1865 // Allow if the origin has a retained allow
1866 if (permissions.hasOrigin(origin)) {
1867 nativeInvokeGeolocationCallback(mNativeAwContents, permissions.isOriginAllowed(origin),
1871 mContentsClient.onGeolocationPermissionsShowPrompt(
1872 origin, new AwGeolocationCallback());
1876 private void onGeolocationPermissionsHidePrompt() {
1877 mContentsClient.onGeolocationPermissionsHidePrompt();
1881 private void onPermissionRequest(AwPermissionRequest awPermissionRequest) {
1882 mContentsClient.onPermissionRequest(awPermissionRequest);
1886 private void onPermissionRequestCanceled(AwPermissionRequest awPermissionRequest) {
1887 mContentsClient.onPermissionRequestCanceled(awPermissionRequest);
1891 public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
1892 boolean isDoneCounting) {
1893 mContentsClient.onFindResultReceived(activeMatchOrdinal, numberOfMatches, isDoneCounting);
1897 public void onNewPicture() {
1898 // Don't call capturePicture() here but instead defer it until the posted task runs within
1899 // the callback helper, to avoid doubling back into the renderer compositor in the middle
1900 // of the notification it is sending up to here.
1901 mContentsClient.getCallbackHelper().postOnNewPicture(mPictureListenerContentProvider);
1904 // Called as a result of nativeUpdateLastHitTestData.
1906 private void updateHitTestData(
1907 int type, String extra, String href, String anchorText, String imgSrc) {
1908 mPossiblyStaleHitTestData.hitTestResultType = type;
1909 mPossiblyStaleHitTestData.hitTestResultExtraData = extra;
1910 mPossiblyStaleHitTestData.href = href;
1911 mPossiblyStaleHitTestData.anchorText = anchorText;
1912 mPossiblyStaleHitTestData.imgSrc = imgSrc;
1916 private boolean requestDrawGL(Canvas canvas, boolean waitForCompletion) {
1917 return mInternalAccessAdapter.requestDrawGL(canvas, waitForCompletion);
1920 private static final boolean SUPPORTS_ON_ANIMATION =
1921 Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
1924 private void postInvalidateOnAnimation() {
1925 if (SUPPORTS_ON_ANIMATION) {
1926 mContainerView.postInvalidateOnAnimation();
1928 mContainerView.postInvalidate();
1933 private int[] getLocationOnScreen() {
1934 int[] result = new int[2];
1935 mContainerView.getLocationOnScreen(result);
1940 private void onWebLayoutPageScaleFactorChanged(float webLayoutPageScaleFactor) {
1941 // This change notification comes from the renderer thread, not from the cc/ impl thread.
1942 mLayoutSizer.onPageScaleChanged(webLayoutPageScaleFactor);
1946 private void onWebLayoutContentsSizeChanged(int widthCss, int heightCss) {
1947 // This change notification comes from the renderer thread, not from the cc/ impl thread.
1948 mLayoutSizer.onContentSizeChanged(widthCss, heightCss);
1952 private void setMaxContainerViewScrollOffset(int maxX, int maxY) {
1953 mScrollOffsetManager.setMaxScrollOffset(maxX, maxY);
1957 private void scrollContainerViewTo(int x, int y) {
1958 mScrollOffsetManager.scrollContainerViewTo(x, y);
1962 private boolean isFlingActive() {
1963 return mScrollOffsetManager.isFlingActive();
1967 private void setContentsSize(int widthDip, int heightDip) {
1968 mContentWidthDip = widthDip;
1969 mContentHeightDip = heightDip;
1973 private void setPageScaleFactorAndLimits(
1974 float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor) {
1975 if (mPageScaleFactor == pageScaleFactor &&
1976 mMinPageScaleFactor == minPageScaleFactor &&
1977 mMaxPageScaleFactor == maxPageScaleFactor) {
1980 mMinPageScaleFactor = minPageScaleFactor;
1981 mMaxPageScaleFactor = maxPageScaleFactor;
1982 if (mPageScaleFactor != pageScaleFactor) {
1983 float oldPageScaleFactor = mPageScaleFactor;
1984 mPageScaleFactor = pageScaleFactor;
1985 // NOTE: if this ever needs to become synchronous then we need to make sure the scroll
1986 // bounds are correctly updated before calling the method, otherwise embedder code that
1987 // attempts to scroll on scale change might cause weird results.
1988 mContentsClient.getCallbackHelper().postOnScaleChangedScaled(
1989 (float)(oldPageScaleFactor * mDIPScale),
1990 (float)(mPageScaleFactor * mDIPScale));
1995 private void setAwAutofillManagerDelegate(AwAutofillManagerDelegate delegate) {
1996 mAwAutofillManagerDelegate = delegate;
1997 delegate.init(mContentViewCore);
2001 private void didOverscroll(int deltaX, int deltaY) {
2002 if (mOverScrollGlow != null) {
2003 mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY);
2006 mScrollOffsetManager.overScrollBy(deltaX, deltaY);
2008 if (mOverScrollGlow != null && mOverScrollGlow.isAnimating()) {
2009 mContainerView.invalidate();
2013 // -------------------------------------------------------------------------------------------
2015 // -------------------------------------------------------------------------------------------
2017 private void saveWebArchiveInternal(String path, final ValueCallback<String> callback) {
2018 if (path == null || mNativeAwContents == 0) {
2019 ThreadUtils.runOnUiThread(new Runnable() {
2022 callback.onReceiveValue(null);
2026 nativeGenerateMHTML(mNativeAwContents, path, callback);
2031 * Try to generate a pathname for saving an MHTML archive. This roughly follows WebView's
2034 private static String generateArchiveAutoNamePath(String originalUrl, String baseName) {
2036 if (originalUrl != null && !originalUrl.isEmpty()) {
2038 String path = new URL(originalUrl).getPath();
2039 int lastSlash = path.lastIndexOf('/');
2040 if (lastSlash > 0) {
2041 name = path.substring(lastSlash + 1);
2045 } catch (MalformedURLException e) {
2046 // If it fails parsing the URL, we'll just rely on the default name below.
2050 if (TextUtils.isEmpty(name)) name = "index";
2052 String testName = baseName + name + WEB_ARCHIVE_EXTENSION;
2053 if (!new File(testName).exists()) return testName;
2055 for (int i = 1; i < 100; i++) {
2056 testName = baseName + name + "-" + i + WEB_ARCHIVE_EXTENSION;
2057 if (!new File(testName).exists()) return testName;
2060 Log.e(TAG, "Unable to auto generate archive name for path: " + baseName);
2064 public void extractSmartClipData(int x, int y, int width, int height) {
2065 mContentViewCore.extractSmartClipData(x, y, width, height);
2068 public void setSmartClipDataListener(ContentViewCore.SmartClipDataListener listener) {
2069 mContentViewCore.setSmartClipDataListener(listener);
2072 //--------------------------------------------------------------------------------------------
2074 //--------------------------------------------------------------------------------------------
2076 private static native long nativeInit(AwBrowserContext browserContext);
2077 private static native void nativeDestroy(long nativeAwContents);
2078 private static native void nativeSetAwDrawSWFunctionTable(long functionTablePointer);
2079 private static native void nativeSetAwDrawGLFunctionTable(long functionTablePointer);
2080 private static native long nativeGetAwDrawGLFunction();
2081 private static native int nativeGetNativeInstanceCount();
2082 private static native void nativeSetShouldDownloadFavicons();
2084 private native void nativeSetJavaPeers(long nativeAwContents, AwContents awContents,
2085 AwWebContentsDelegate webViewWebContentsDelegate,
2086 AwContentsClientBridge contentsClientBridge,
2087 AwContentsIoThreadClient ioThreadClient,
2088 InterceptNavigationDelegate navigationInterceptionDelegate);
2089 private native long nativeGetWebContents(long nativeAwContents);
2091 private native void nativeDocumentHasImages(long nativeAwContents, Message message);
2092 private native void nativeGenerateMHTML(
2093 long nativeAwContents, String path, ValueCallback<String> callback);
2095 private native void nativeAddVisitedLinks(long nativeAwContents, String[] visitedLinks);
2096 private native boolean nativeOnDraw(long nativeAwContents, Canvas canvas,
2097 boolean isHardwareAccelerated, int scrollX, int scrollY,
2098 int visibleLeft, int visibleTop, int visibleRight, int visibleBottom,
2099 int clipLeft, int clipTop, int clipRight, int clipBottom);
2100 private native void nativeFindAllAsync(long nativeAwContents, String searchString);
2101 private native void nativeFindNext(long nativeAwContents, boolean forward);
2102 private native void nativeClearMatches(long nativeAwContents);
2103 private native void nativeClearCache(long nativeAwContents, boolean includeDiskFiles);
2104 private native byte[] nativeGetCertificate(long nativeAwContents);
2106 // Coordinates in desity independent pixels.
2107 private native void nativeRequestNewHitTestDataAt(long nativeAwContents, int x, int y);
2108 private native void nativeUpdateLastHitTestData(long nativeAwContents);
2110 private native void nativeOnSizeChanged(long nativeAwContents, int w, int h, int ow, int oh);
2111 private native void nativeScrollTo(long nativeAwContents, int x, int y);
2112 private native void nativeSetViewVisibility(long nativeAwContents, boolean visible);
2113 private native void nativeSetWindowVisibility(long nativeAwContents, boolean visible);
2114 private native void nativeSetIsPaused(long nativeAwContents, boolean paused);
2115 private native void nativeOnAttachedToWindow(long nativeAwContents, int w, int h);
2116 private static native void nativeOnDetachedFromWindow(long nativeAwContents);
2117 private native void nativeSetDipScale(long nativeAwContents, float dipScale);
2118 private native void nativeSetFixedLayoutSize(long nativeAwContents,
2119 int widthDip, int heightDip);
2121 // Returns null if save state fails.
2122 private native byte[] nativeGetOpaqueState(long nativeAwContents);
2124 // Returns false if restore state fails.
2125 private native boolean nativeRestoreFromOpaqueState(long nativeAwContents, byte[] state);
2127 private native long nativeReleasePopupAwContents(long nativeAwContents);
2128 private native void nativeFocusFirstNode(long nativeAwContents);
2129 private native void nativeSetBackgroundColor(long nativeAwContents, int color);
2131 private native long nativeGetAwDrawGLViewContext(long nativeAwContents);
2132 private native long nativeCapturePicture(long nativeAwContents, int width, int height);
2133 private native void nativeEnableOnNewPicture(long nativeAwContents, boolean enabled);
2134 private native void nativeClearView(long nativeAwContents);
2135 private native void nativeSetExtraHeadersForUrl(long nativeAwContents,
2136 String url, String extraHeaders);
2138 private native void nativeInvokeGeolocationCallback(
2139 long nativeAwContents, boolean value, String requestingFrame);
2141 private native void nativeSetJsOnlineProperty(long nativeAwContents, boolean networkUp);
2143 private native void nativeTrimMemory(long nativeAwContents, int level, boolean visible);
2145 private native void nativeCreatePdfExporter(long nativeAwContents, AwPdfExporter awPdfExporter);
2147 private native void nativePreauthorizePermission(long nativeAwContents, String origin,