| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.content.browser.webcontents; |
| |
| import android.annotation.SuppressLint; |
| import android.graphics.Bitmap; |
| import android.graphics.Rect; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.Message; |
| import android.os.Parcel; |
| import android.os.ParcelUuid; |
| import android.os.Parcelable; |
| import android.support.annotation.Nullable; |
| |
| import org.chromium.base.Log; |
| import org.chromium.base.ThreadUtils; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.base.annotations.CalledByNative; |
| import org.chromium.base.annotations.JNINamespace; |
| import org.chromium.content.browser.AppWebMessagePort; |
| import org.chromium.content.browser.MediaSessionImpl; |
| import org.chromium.content.browser.RenderCoordinates; |
| import org.chromium.content.browser.framehost.RenderFrameHostDelegate; |
| import org.chromium.content.browser.framehost.RenderFrameHostImpl; |
| import org.chromium.content_public.browser.AccessibilitySnapshotCallback; |
| import org.chromium.content_public.browser.AccessibilitySnapshotNode; |
| import org.chromium.content_public.browser.ChildProcessImportance; |
| import org.chromium.content_public.browser.ContentBitmapCallback; |
| import org.chromium.content_public.browser.ImageDownloadCallback; |
| import org.chromium.content_public.browser.JavaScriptCallback; |
| import org.chromium.content_public.browser.MessagePort; |
| import org.chromium.content_public.browser.NavigationController; |
| import org.chromium.content_public.browser.RenderFrameHost; |
| import org.chromium.content_public.browser.WebContents; |
| import org.chromium.content_public.browser.WebContentsInternals; |
| import org.chromium.content_public.browser.WebContentsObserver; |
| import org.chromium.ui.OverscrollRefreshHandler; |
| import org.chromium.ui.base.EventForwarder; |
| import org.chromium.ui.base.WindowAndroid; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.UUID; |
| |
| /** |
| * The WebContentsImpl Java wrapper to allow communicating with the native WebContentsImpl |
| * object. |
| */ |
| @JNINamespace("content") |
| public class WebContentsImpl implements WebContents, RenderFrameHostDelegate { |
| private static final String TAG = "cr_WebContentsImpl"; |
| |
| private static final String PARCEL_VERSION_KEY = "version"; |
| private static final String PARCEL_WEBCONTENTS_KEY = "webcontents"; |
| private static final String PARCEL_PROCESS_GUARD_KEY = "processguard"; |
| |
| private static final long PARCELABLE_VERSION_ID = 0; |
| // Non-final for testing purposes, so resetting of the UUID can happen. |
| private static UUID sParcelableUUID = UUID.randomUUID(); |
| |
| /** |
| * Used to reset the internal tracking for whether or not a serialized {@link WebContents} |
| * was created in this process or not. |
| */ |
| @VisibleForTesting |
| public static void invalidateSerializedWebContentsForTesting() { |
| sParcelableUUID = UUID.randomUUID(); |
| } |
| |
| /** |
| * A {@link android.os.Parcelable.Creator} instance that is used to build |
| * {@link WebContentsImpl} objects from a {@link Parcel}. |
| */ |
| // TODO(crbug.com/635567): Fix this properly. |
| @SuppressLint("ParcelClassLoader") |
| public static final Parcelable.Creator<WebContents> CREATOR = |
| new Parcelable.Creator<WebContents>() { |
| @Override |
| public WebContents createFromParcel(Parcel source) { |
| Bundle bundle = source.readBundle(); |
| |
| // Check the version. |
| if (bundle.getLong(PARCEL_VERSION_KEY, -1) != 0) return null; |
| |
| // Check that we're in the same process. |
| ParcelUuid parcelUuid = bundle.getParcelable(PARCEL_PROCESS_GUARD_KEY); |
| if (sParcelableUUID.compareTo(parcelUuid.getUuid()) != 0) return null; |
| |
| // Attempt to retrieve the WebContents object from the native pointer. |
| return nativeFromNativePtr(bundle.getLong(PARCEL_WEBCONTENTS_KEY)); |
| } |
| |
| @Override |
| public WebContents[] newArray(int size) { |
| return new WebContents[size]; |
| } |
| }; |
| |
| // Note this list may be incomplete. Frames that never had to initialize java side would |
| // not have an entry here. This is here mainly to keep the java RenderFrameHosts alive, since |
| // native side generally cannot safely hold strong references to them. |
| private final List<RenderFrameHostImpl> mFrames = new ArrayList<>(); |
| |
| private long mNativeWebContentsAndroid; |
| private NavigationController mNavigationController; |
| |
| // Lazily created proxy observer for handling all Java-based WebContentsObservers. |
| private WebContentsObserverProxy mObserverProxy; |
| |
| // The media session for this WebContents. It is constructed by the native MediaSession and has |
| // the same life time as native MediaSession. |
| private MediaSessionImpl mMediaSession; |
| |
| private class SmartClipCallback { |
| public SmartClipCallback(final Handler smartClipHandler) { |
| mHandler = smartClipHandler; |
| } |
| public void storeRequestRect(Rect rect) { |
| mRect = rect; |
| } |
| |
| public void onSmartClipDataExtracted(String text, String html) { |
| Bundle bundle = new Bundle(); |
| bundle.putString("url", getVisibleUrl()); |
| bundle.putString("title", getTitle()); |
| bundle.putString("text", text); |
| bundle.putString("html", html); |
| bundle.putParcelable("rect", mRect); |
| |
| Message msg = Message.obtain(mHandler, 0); |
| msg.setData(bundle); |
| msg.sendToTarget(); |
| } |
| |
| Rect mRect; |
| final Handler mHandler; |
| } |
| private SmartClipCallback mSmartClipCallback; |
| |
| private EventForwarder mEventForwarder; |
| |
| private static class DefaultInternalsHolder implements InternalsHolder { |
| private WebContentsInternals mInternals; |
| |
| @Override |
| public void set(WebContentsInternals internals) { |
| mInternals = internals; |
| } |
| |
| @Override |
| public WebContentsInternals get() { |
| return mInternals; |
| } |
| } |
| |
| // Cached copy of all positions and scales as reported by the renderer. |
| private RenderCoordinates mRenderCoordinates; |
| |
| private InternalsHolder mInternalsHolder; |
| |
| private static class WebContentsInternalsImpl implements WebContentsInternals { |
| public HashMap<Class, WebContentsUserData> userDataMap; |
| } |
| |
| private WebContentsImpl( |
| long nativeWebContentsAndroid, NavigationController navigationController) { |
| mNativeWebContentsAndroid = nativeWebContentsAndroid; |
| mNavigationController = navigationController; |
| |
| // Initialize |mInternalsHolder| with a default one that keeps all the internals |
| // inside WebContentsImpl. It holds a strong reference until an embedder invokes |
| // |setInternalsHolder| to get the internals handed over to it. |
| WebContentsInternalsImpl internals = new WebContentsInternalsImpl(); |
| internals.userDataMap = new HashMap<>(); |
| |
| mRenderCoordinates = new RenderCoordinates(); |
| mRenderCoordinates.reset(); |
| |
| mInternalsHolder = new DefaultInternalsHolder(); |
| mInternalsHolder.set(internals); |
| } |
| |
| @CalledByNative |
| private static WebContentsImpl create( |
| long nativeWebContentsAndroid, NavigationController navigationController) { |
| return new WebContentsImpl(nativeWebContentsAndroid, navigationController); |
| } |
| |
| @CalledByNative |
| private void clearNativePtr() { |
| mNativeWebContentsAndroid = 0; |
| mNavigationController = null; |
| if (mObserverProxy != null) { |
| mObserverProxy.destroy(); |
| mObserverProxy = null; |
| } |
| } |
| |
| @Override |
| public void setInternalsHolder(InternalsHolder internalsHolder) { |
| // Ensure |setInternalsHolder()| is be called at most once. |
| assert mInternalsHolder instanceof DefaultInternalsHolder; |
| internalsHolder.set(mInternalsHolder.get()); |
| mInternalsHolder = internalsHolder; |
| } |
| |
| // =================== RenderFrameHostDelegate overrides =================== |
| @Override |
| public void renderFrameCreated(RenderFrameHostImpl host) { |
| assert !mFrames.contains(host); |
| mFrames.add(host); |
| } |
| |
| @Override |
| public void renderFrameDeleted(RenderFrameHostImpl host) { |
| assert mFrames.contains(host); |
| mFrames.remove(host); |
| } |
| // ================= end RenderFrameHostDelegate overrides ================= |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| // This is wrapped in a Bundle so that failed deserialization attempts don't corrupt the |
| // overall Parcel. If we failed a UUID or Version check and didn't read the rest of the |
| // fields it would corrupt the serialized stream. |
| Bundle data = new Bundle(); |
| data.putLong(PARCEL_VERSION_KEY, PARCELABLE_VERSION_ID); |
| data.putParcelable(PARCEL_PROCESS_GUARD_KEY, new ParcelUuid(sParcelableUUID)); |
| data.putLong(PARCEL_WEBCONTENTS_KEY, mNativeWebContentsAndroid); |
| dest.writeBundle(data); |
| } |
| |
| @CalledByNative |
| private long getNativePointer() { |
| return mNativeWebContentsAndroid; |
| } |
| |
| @Override |
| public WindowAndroid getTopLevelNativeWindow() { |
| return nativeGetTopLevelNativeWindow(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void destroy() { |
| if (!ThreadUtils.runningOnUiThread()) { |
| throw new IllegalStateException("Attempting to destroy WebContents on non-UI thread"); |
| } |
| if (mNativeWebContentsAndroid != 0) nativeDestroyWebContents(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isDestroyed() { |
| return mNativeWebContentsAndroid == 0; |
| } |
| |
| @Override |
| public NavigationController getNavigationController() { |
| return mNavigationController; |
| } |
| |
| @Override |
| public RenderFrameHost getMainFrame() { |
| return nativeGetMainFrame(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public String getTitle() { |
| return nativeGetTitle(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public String getVisibleUrl() { |
| return nativeGetVisibleURL(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public String getEncoding() { |
| return nativeGetEncoding(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isLoading() { |
| return nativeIsLoading(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isLoadingToDifferentDocument() { |
| return nativeIsLoadingToDifferentDocument(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void stop() { |
| nativeStop(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void cut() { |
| nativeCut(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void copy() { |
| nativeCopy(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void paste() { |
| nativePaste(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void pasteAsPlainText() { |
| nativePasteAsPlainText(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void replace(String word) { |
| nativeReplace(mNativeWebContentsAndroid, word); |
| } |
| |
| @Override |
| public void selectAll() { |
| nativeSelectAll(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void collapseSelection() { |
| // collapseSelection may get triggered when certain selection-related widgets |
| // are destroyed. As the timing for such destruction is unpredictable, |
| // safely guard against this case. |
| if (isDestroyed()) return; |
| nativeCollapseSelection(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void onHide() { |
| nativeOnHide(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void onShow() { |
| nativeOnShow(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void setImportance(@ChildProcessImportance int importance) { |
| nativeSetImportance(mNativeWebContentsAndroid, importance); |
| } |
| |
| @Override |
| public void suspendAllMediaPlayers() { |
| nativeSuspendAllMediaPlayers(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void setAudioMuted(boolean mute) { |
| nativeSetAudioMuted(mNativeWebContentsAndroid, mute); |
| } |
| |
| @Override |
| public int getBackgroundColor() { |
| return nativeGetBackgroundColor(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void showInterstitialPage( |
| String url, long interstitialPageDelegateAndroid) { |
| nativeShowInterstitialPage(mNativeWebContentsAndroid, url, interstitialPageDelegateAndroid); |
| } |
| |
| @Override |
| public boolean isShowingInterstitialPage() { |
| return nativeIsShowingInterstitialPage(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean focusLocationBarByDefault() { |
| return nativeFocusLocationBarByDefault(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isReady() { |
| return nativeIsRenderWidgetHostViewReady(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void exitFullscreen() { |
| nativeExitFullscreen(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void scrollFocusedEditableNodeIntoView() { |
| // The native side keeps track of whether the zoom and scroll actually occurred. It is |
| // more efficient to do it this way and sometimes fire an unnecessary message rather |
| // than synchronize with the renderer and always have an additional message. |
| nativeScrollFocusedEditableNodeIntoView(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void selectWordAroundCaret() { |
| nativeSelectWordAroundCaret(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void adjustSelectionByCharacterOffset( |
| int startAdjust, int endAdjust, boolean showSelectionMenu) { |
| nativeAdjustSelectionByCharacterOffset( |
| mNativeWebContentsAndroid, startAdjust, endAdjust, showSelectionMenu); |
| } |
| |
| @Override |
| public String getLastCommittedUrl() { |
| return nativeGetLastCommittedURL(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isIncognito() { |
| return nativeIsIncognito(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void resumeLoadingCreatedWebContents() { |
| nativeResumeLoadingCreatedWebContents(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void evaluateJavaScript(String script, JavaScriptCallback callback) { |
| if (isDestroyed() || script == null) return; |
| nativeEvaluateJavaScript(mNativeWebContentsAndroid, script, callback); |
| } |
| |
| @Override |
| @VisibleForTesting |
| public void evaluateJavaScriptForTests(String script, JavaScriptCallback callback) { |
| if (script == null) return; |
| nativeEvaluateJavaScriptForTests(mNativeWebContentsAndroid, script, callback); |
| } |
| |
| @Override |
| public void addMessageToDevToolsConsole(int level, String message) { |
| nativeAddMessageToDevToolsConsole(mNativeWebContentsAndroid, level, message); |
| } |
| |
| @Override |
| public void postMessageToFrame(String frameName, String message, |
| String sourceOrigin, String targetOrigin, MessagePort[] ports) { |
| if (ports != null) { |
| for (MessagePort port : ports) { |
| if (port.isClosed() || port.isTransferred()) { |
| throw new IllegalStateException("Port is already closed or transferred"); |
| } |
| if (port.isStarted()) { |
| throw new IllegalStateException("Port is already started"); |
| } |
| } |
| } |
| // Treat "*" as a wildcard. Internally, a wildcard is a empty string. |
| if (targetOrigin.equals("*")) { |
| targetOrigin = ""; |
| } |
| nativePostMessageToFrame( |
| mNativeWebContentsAndroid, frameName, message, sourceOrigin, targetOrigin, ports); |
| } |
| |
| @Override |
| public AppWebMessagePort[] createMessageChannel() |
| throws IllegalStateException { |
| return AppWebMessagePort.createPair(); |
| } |
| |
| @Override |
| public boolean hasAccessedInitialDocument() { |
| return nativeHasAccessedInitialDocument(mNativeWebContentsAndroid); |
| } |
| |
| @CalledByNative |
| private static void onEvaluateJavaScriptResult( |
| String jsonResult, JavaScriptCallback callback) { |
| callback.handleJavaScriptResult(jsonResult); |
| } |
| |
| @Override |
| public int getThemeColor() { |
| return nativeGetThemeColor(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void requestSmartClipExtract(int x, int y, int width, int height) { |
| if (mSmartClipCallback == null) return; |
| mSmartClipCallback.storeRequestRect(new Rect(x, y, x + width, y + height)); |
| RenderCoordinates coordinateSpace = getRenderCoordinates(); |
| float dpi = coordinateSpace.getDeviceScaleFactor(); |
| y = (int) (y - coordinateSpace.getContentOffsetYPix()); |
| nativeRequestSmartClipExtract(mNativeWebContentsAndroid, mSmartClipCallback, |
| (int) (x / dpi), (int) (y / dpi), (int) (width / dpi), (int) (height / dpi)); |
| } |
| |
| @Override |
| public void setSmartClipResultHandler(final Handler smartClipHandler) { |
| if (smartClipHandler == null) { |
| mSmartClipCallback = null; |
| return; |
| } |
| mSmartClipCallback = new SmartClipCallback(smartClipHandler); |
| } |
| |
| @CalledByNative |
| private static void onSmartClipDataExtracted( |
| String text, String html, SmartClipCallback callback) { |
| callback.onSmartClipDataExtracted(text, html); |
| } |
| |
| @Override |
| public void requestAccessibilitySnapshot(AccessibilitySnapshotCallback callback) { |
| nativeRequestAccessibilitySnapshot(mNativeWebContentsAndroid, callback); |
| } |
| |
| @Override |
| @VisibleForTesting |
| public void simulateRendererKilledForTesting(boolean wasOomProtected) { |
| if (mObserverProxy != null) { |
| mObserverProxy.renderProcessGone(wasOomProtected); |
| } |
| } |
| |
| // root node can be null if parsing fails. |
| @CalledByNative |
| private static void onAccessibilitySnapshot(AccessibilitySnapshotNode root, |
| AccessibilitySnapshotCallback callback) { |
| callback.onAccessibilitySnapshot(root); |
| } |
| |
| @CalledByNative |
| private static void addAccessibilityNodeAsChild(AccessibilitySnapshotNode parent, |
| AccessibilitySnapshotNode child) { |
| parent.addChild(child); |
| } |
| |
| @CalledByNative |
| private static AccessibilitySnapshotNode createAccessibilitySnapshotNode(int parentRelativeLeft, |
| int parentRelativeTop, int width, int height, boolean isRootNode, String text, |
| int color, int bgcolor, float size, boolean bold, boolean italic, boolean underline, |
| boolean lineThrough, String className) { |
| AccessibilitySnapshotNode node = new AccessibilitySnapshotNode(text, className); |
| |
| // if size is smaller than 0, then style information does not exist. |
| if (size >= 0.0) { |
| node.setStyle(color, bgcolor, size, bold, italic, underline, lineThrough); |
| } |
| node.setLocationInfo(parentRelativeLeft, parentRelativeTop, width, height, isRootNode); |
| return node; |
| } |
| |
| @CalledByNative |
| private static void setAccessibilitySnapshotSelection( |
| AccessibilitySnapshotNode node, int start, int end) { |
| node.setSelection(start, end); |
| } |
| |
| @Override |
| public EventForwarder getEventForwarder() { |
| assert mNativeWebContentsAndroid != 0; |
| if (mEventForwarder == null) { |
| mEventForwarder = nativeGetOrCreateEventForwarder(mNativeWebContentsAndroid); |
| } |
| return mEventForwarder; |
| } |
| |
| @Override |
| public void addObserver(WebContentsObserver observer) { |
| assert mNativeWebContentsAndroid != 0; |
| if (mObserverProxy == null) mObserverProxy = new WebContentsObserverProxy(this); |
| mObserverProxy.addObserver(observer); |
| } |
| |
| @Override |
| public void removeObserver(WebContentsObserver observer) { |
| if (mObserverProxy == null) return; |
| mObserverProxy.removeObserver(observer); |
| } |
| |
| @Override |
| public void setOverscrollRefreshHandler(OverscrollRefreshHandler handler) { |
| nativeSetOverscrollRefreshHandler(mNativeWebContentsAndroid, handler); |
| } |
| |
| @Override |
| public void getContentBitmapAsync(int width, int height, ContentBitmapCallback callback) { |
| nativeGetContentBitmap(mNativeWebContentsAndroid, width, height, callback); |
| } |
| |
| @CalledByNative |
| private void onGetContentBitmapFinished(ContentBitmapCallback callback, Bitmap bitmap, |
| int response) { |
| callback.onFinishGetBitmap(bitmap, response); |
| } |
| |
| @Override |
| public void reloadLoFiImages() { |
| nativeReloadLoFiImages(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public int downloadImage(String url, boolean isFavicon, int maxBitmapSize, |
| boolean bypassCache, ImageDownloadCallback callback) { |
| return nativeDownloadImage(mNativeWebContentsAndroid, |
| url, isFavicon, maxBitmapSize, bypassCache, callback); |
| } |
| |
| @CalledByNative |
| private void onDownloadImageFinished(ImageDownloadCallback callback, int id, int httpStatusCode, |
| String imageUrl, List<Bitmap> bitmaps, List<Rect> sizes) { |
| callback.onFinishDownloadImage(id, httpStatusCode, imageUrl, bitmaps, sizes); |
| } |
| |
| @Override |
| public void dismissTextHandles() { |
| nativeDismissTextHandles(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void showContextMenuAtTouchHandle(int x, int y) { |
| nativeShowContextMenuAtTouchHandle(mNativeWebContentsAndroid, x, y); |
| } |
| |
| @Override |
| public void setHasPersistentVideo(boolean value) { |
| nativeSetHasPersistentVideo(mNativeWebContentsAndroid, value); |
| } |
| |
| @Override |
| public boolean hasActiveEffectivelyFullscreenVideo() { |
| return nativeHasActiveEffectivelyFullscreenVideo(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public boolean isPictureInPictureAllowedForFullscreenVideo() { |
| return nativeIsPictureInPictureAllowedForFullscreenVideo(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public @Nullable Rect getFullscreenVideoSize() { |
| return nativeGetFullscreenVideoSize(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public void setSize(int width, int height) { |
| nativeSetSize(mNativeWebContentsAndroid, width, height); |
| } |
| |
| @Override |
| public int getWidth() { |
| return nativeGetWidth(mNativeWebContentsAndroid); |
| } |
| |
| @Override |
| public int getHeight() { |
| return nativeGetHeight(mNativeWebContentsAndroid); |
| } |
| |
| @CalledByNative |
| private final void setMediaSession(MediaSessionImpl mediaSession) { |
| mMediaSession = mediaSession; |
| } |
| |
| @CalledByNative |
| private static List<Bitmap> createBitmapList() { |
| return new ArrayList<Bitmap>(); |
| } |
| |
| @CalledByNative |
| private static void addToBitmapList(List<Bitmap> bitmaps, Bitmap bitmap) { |
| bitmaps.add(bitmap); |
| } |
| |
| @CalledByNative |
| private static List<Rect> createSizeList() { |
| return new ArrayList<Rect>(); |
| } |
| |
| @CalledByNative |
| private static void createSizeAndAddToList(List<Rect> sizes, int width, int height) { |
| sizes.add(new Rect(0, 0, width, height)); |
| } |
| |
| @CalledByNative |
| private static Rect createSize(int width, int height) { |
| return new Rect(0, 0, width, height); |
| } |
| |
| /** |
| * Returns {@link RenderCoordinates}. This method is intended for use in content layer only. |
| */ |
| public RenderCoordinates getRenderCoordinates() { |
| return mRenderCoordinates; |
| } |
| |
| /** |
| * Sets {@link WebContentsUserData} object in {@code UserDataMap}. |
| * <p> |
| * Note: This should be only called by {@link WebContentsUserData}. |
| * @param key Key of the generic object to set (its class instance). |
| * @param data The wrapper {@link WebContentsUserData} of the generic object to store. |
| */ |
| void setUserData(Class key, WebContentsUserData data) { |
| Map<Class, WebContentsUserData> userDataMap = getUserDataMap(); |
| if (userDataMap == null) { |
| Log.e(TAG, "UserDataMap can't be found"); |
| return; |
| } |
| assert !userDataMap.containsKey(key); // Do not allow duplicated Data |
| userDataMap.put(key, data); |
| } |
| |
| /** |
| * Gets {@link WebContentsUserData} object from {@code UserDataMap}. |
| * <p> |
| * Note: This should be only called by {@link WebContentsUserData}. |
| * @param key Key of the generic object wrapped in {@link WebContentsUserData}. |
| * @return The {@link WebContentUserData} wrapping the object associated with the key. |
| */ |
| WebContentsUserData getUserData(Class key) { |
| Map<Class, WebContentsUserData> userDataMap = getUserDataMap(); |
| return userDataMap != null ? userDataMap.get(key) : null; |
| } |
| |
| /** |
| * Note: This should be only called by {@link WebContentsUserData}. |
| * @return {@code UserDataMap} that contains internal user data. {@code null} if |
| * the map is already gc'ed. |
| */ |
| Map<Class, WebContentsUserData> getUserDataMap() { |
| WebContentsInternals internals = mInternalsHolder.get(); |
| if (internals == null) return null; |
| return ((WebContentsInternalsImpl) internals).userDataMap; |
| } |
| |
| // This is static to avoid exposing a public destroy method on the native side of this class. |
| private static native void nativeDestroyWebContents(long webContentsAndroidPtr); |
| |
| private static native WebContents nativeFromNativePtr(long webContentsAndroidPtr); |
| |
| private native WindowAndroid nativeGetTopLevelNativeWindow(long nativeWebContentsAndroid); |
| private native RenderFrameHost nativeGetMainFrame(long nativeWebContentsAndroid); |
| private native String nativeGetTitle(long nativeWebContentsAndroid); |
| private native String nativeGetVisibleURL(long nativeWebContentsAndroid); |
| private native String nativeGetEncoding(long nativeWebContentsAndroid); |
| private native boolean nativeIsLoading(long nativeWebContentsAndroid); |
| private native boolean nativeIsLoadingToDifferentDocument(long nativeWebContentsAndroid); |
| private native void nativeStop(long nativeWebContentsAndroid); |
| private native void nativeCut(long nativeWebContentsAndroid); |
| private native void nativeCopy(long nativeWebContentsAndroid); |
| private native void nativePaste(long nativeWebContentsAndroid); |
| private native void nativePasteAsPlainText(long nativeWebContentsAndroid); |
| private native void nativeReplace(long nativeWebContentsAndroid, String word); |
| private native void nativeSelectAll(long nativeWebContentsAndroid); |
| private native void nativeCollapseSelection(long nativeWebContentsAndroid); |
| private native void nativeOnHide(long nativeWebContentsAndroid); |
| private native void nativeOnShow(long nativeWebContentsAndroid); |
| private native void nativeSetImportance(long nativeWebContentsAndroid, int importance); |
| private native void nativeSuspendAllMediaPlayers(long nativeWebContentsAndroid); |
| private native void nativeSetAudioMuted(long nativeWebContentsAndroid, boolean mute); |
| private native int nativeGetBackgroundColor(long nativeWebContentsAndroid); |
| private native void nativeShowInterstitialPage(long nativeWebContentsAndroid, |
| String url, long nativeInterstitialPageDelegateAndroid); |
| private native boolean nativeIsShowingInterstitialPage(long nativeWebContentsAndroid); |
| private native boolean nativeFocusLocationBarByDefault(long nativeWebContentsAndroid); |
| private native boolean nativeIsRenderWidgetHostViewReady(long nativeWebContentsAndroid); |
| private native void nativeExitFullscreen(long nativeWebContentsAndroid); |
| private native void nativeScrollFocusedEditableNodeIntoView(long nativeWebContentsAndroid); |
| private native void nativeSelectWordAroundCaret(long nativeWebContentsAndroid); |
| private native void nativeAdjustSelectionByCharacterOffset(long nativeWebContentsAndroid, |
| int startAdjust, int endAdjust, boolean showSelectionMenu); |
| private native String nativeGetLastCommittedURL(long nativeWebContentsAndroid); |
| private native boolean nativeIsIncognito(long nativeWebContentsAndroid); |
| private native void nativeResumeLoadingCreatedWebContents(long nativeWebContentsAndroid); |
| private native void nativeEvaluateJavaScript(long nativeWebContentsAndroid, |
| String script, JavaScriptCallback callback); |
| private native void nativeEvaluateJavaScriptForTests(long nativeWebContentsAndroid, |
| String script, JavaScriptCallback callback); |
| private native void nativeAddMessageToDevToolsConsole( |
| long nativeWebContentsAndroid, int level, String message); |
| private native void nativePostMessageToFrame(long nativeWebContentsAndroid, String frameName, |
| String message, String sourceOrigin, String targetOrigin, MessagePort[] ports); |
| private native boolean nativeHasAccessedInitialDocument( |
| long nativeWebContentsAndroid); |
| private native int nativeGetThemeColor(long nativeWebContentsAndroid); |
| private native void nativeRequestSmartClipExtract(long nativeWebContentsAndroid, |
| SmartClipCallback callback, int x, int y, int width, int height); |
| private native void nativeRequestAccessibilitySnapshot( |
| long nativeWebContentsAndroid, AccessibilitySnapshotCallback callback); |
| private native void nativeSetOverscrollRefreshHandler( |
| long nativeWebContentsAndroid, OverscrollRefreshHandler nativeOverscrollRefreshHandler); |
| private native void nativeGetContentBitmap( |
| long nativeWebContentsAndroid, int width, int height, ContentBitmapCallback callback); |
| private native void nativeReloadLoFiImages(long nativeWebContentsAndroid); |
| private native int nativeDownloadImage(long nativeWebContentsAndroid, |
| String url, boolean isFavicon, int maxBitmapSize, |
| boolean bypassCache, ImageDownloadCallback callback); |
| private native void nativeDismissTextHandles(long nativeWebContentsAndroid); |
| private native void nativeShowContextMenuAtTouchHandle( |
| long nativeWebContentsAndroid, int x, int y); |
| private native void nativeSetHasPersistentVideo(long nativeWebContentsAndroid, boolean value); |
| private native boolean nativeHasActiveEffectivelyFullscreenVideo(long nativeWebContentsAndroid); |
| private native boolean nativeIsPictureInPictureAllowedForFullscreenVideo( |
| long nativeWebContentsAndroid); |
| private native Rect nativeGetFullscreenVideoSize(long nativeWebContentsAndroid); |
| private native void nativeSetSize(long nativeWebContentsAndroid, int width, int height); |
| private native int nativeGetWidth(long nativeWebContentsAndroid); |
| private native int nativeGetHeight(long nativeWebContentsAndroid); |
| private native EventForwarder nativeGetOrCreateEventForwarder(long nativeWebContentsAndroid); |
| } |