Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
similarity index 66% |
copy from content/public/android/java/src/org/chromium/content/browser/ContentView.java |
copy to content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
index 893fdff624cd83d5cd599ffcea40a6ced86abacc..00969d8cf17540931731ce96db08cb2b533492d6 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
@@ -5,20 +5,27 @@ |
package org.chromium.content.browser; |
import android.content.Context; |
-import android.util.AttributeSet; |
+import android.content.res.Configuration; |
+import android.graphics.Canvas; |
import android.util.Log; |
+import android.view.KeyEvent; |
+import android.view.MotionEvent; |
import android.view.View; |
+import android.view.ViewGroup; |
import android.webkit.DownloadListener; |
-import android.widget.FrameLayout; |
import org.chromium.base.CalledByNative; |
import org.chromium.base.JNINamespace; |
import org.chromium.base.WeakContext; |
-import org.chromium.content.app.AppResource; |
import org.chromium.content.common.TraceEvent; |
+/** |
+ * Contains all the major functionality necessary to manage the lifecycle of a ContentView without |
+ * being tied to the view system. |
+ */ |
@JNINamespace("content") |
-public class ContentView extends FrameLayout { |
+public class ContentViewCore { |
+ private static final String TAG = ContentViewCore.class.getName(); |
// The following constants match the ones in chrome/common/page_transition_types.h. |
// Add more if you need them. |
@@ -27,7 +34,12 @@ public class ContentView extends FrameLayout { |
public static final int PAGE_TRANSITION_AUTO_BOOKMARK = 2; |
public static final int PAGE_TRANSITION_START_PAGE = 6; |
- private static final String TAG = "ContentView"; |
+ /** Translate the find selection into a normal selection. */ |
+ public static final int FIND_SELECTION_ACTION_KEEP_SELECTION = 0; |
+ /** Clear the find selection. */ |
+ public static final int FIND_SELECTION_ACTION_CLEAR_SELECTION = 1; |
+ /** Focus and click the selected node (for links). */ |
+ public static final int FIND_SELECTION_ACTION_ACTIVATE_SELECTION = 2; |
// Personality of the ContentView. |
private int mPersonality; |
@@ -36,21 +48,71 @@ public class ContentView extends FrameLayout { |
// Used for Chrome. |
public static final int PERSONALITY_CHROME = 1; |
- /** |
- * Automatically decide the number of renderer processes to use based on device memory class. |
- * */ |
- public static final int MAX_RENDERERS_AUTOMATIC = AndroidBrowserProcess.MAX_RENDERERS_AUTOMATIC; |
- /** |
- * Use single-process mode that runs the renderer on a separate thread in the main application. |
- */ |
- public static final int MAX_RENDERERS_SINGLE_PROCESS = |
- AndroidBrowserProcess.MAX_RENDERERS_SINGLE_PROCESS; |
- |
// Used to avoid enabling zooming in / out in WebView zoom controls |
// if resulting zooming will produce little visible difference. |
private static float WEBVIEW_ZOOM_CONTROLS_EPSILON = 0.007f; |
- // content_view_client.cc depends on ContentView.java holding a ref to the current client |
+ /** |
+ * Interface that consumers of {@link ContentViewCore} must implement to allow the proper |
+ * dispatching of view methods through the containing view. |
+ * |
+ * <p> |
+ * All methods with the "super_" prefix should be routed to the parent of the |
+ * implementing container view. |
+ */ |
+ @SuppressWarnings("javadoc") |
+ public static interface InternalAccessDelegate { |
+ /** |
+ * @see View#drawChild(Canvas, View, long) |
+ */ |
+ boolean drawChild(Canvas canvas, View child, long drawingTime); |
+ |
+ /** |
+ * @see View#onKeyUp(keyCode, KeyEvent) |
+ */ |
+ boolean super_onKeyUp(int keyCode, KeyEvent event); |
+ |
+ /** |
+ * @see View#dispatchKeyEventPreIme(KeyEvent) |
+ */ |
+ boolean super_dispatchKeyEventPreIme(KeyEvent event); |
+ |
+ /** |
+ * @see View#dispatchKeyEvent(KeyEvent) |
+ */ |
+ boolean super_dispatchKeyEvent(KeyEvent event); |
+ |
+ /** |
+ * @see View#onGenericMotionEvent(MotionEvent) |
+ */ |
+ boolean super_onGenericMotionEvent(MotionEvent event); |
+ |
+ /** |
+ * @see View#onConfigurationChanged(Configuration) |
+ */ |
+ void super_onConfigurationChanged(Configuration newConfig); |
+ |
+ /** |
+ * @see View#onScrollChanged(int, int, int, int) |
+ */ |
+ void onScrollChanged(int l, int t, int oldl, int oldt); |
+ |
+ /** |
+ * @see View#awakenScrollBars() |
+ */ |
+ boolean awakenScrollBars(); |
+ |
+ /** |
+ * @see View#awakenScrollBars(int, boolean) |
+ */ |
+ boolean super_awakenScrollBars(int startDelay, boolean invalidate); |
+ } |
+ |
+ private Context mContext; |
+ private ViewGroup mContainerView; |
+ private InternalAccessDelegate mContainerViewInternals; |
+ |
+ // content_view_client.cc depends on ContentViewCore.java holding a ref to the current client |
// instance since the native side only holds a weak pointer to the client. We chose this |
// solution over the managed object owning the C++ object's memory since it's a lot simpler |
// in terms of clean up. |
@@ -59,7 +121,7 @@ public class ContentView extends FrameLayout { |
private ContentSettings mContentSettings; |
// Native pointer to C++ ContentView object which will be set by nativeInit() |
- private int mNativeContentView = 0; |
+ private int mNativeContentViewCore = 0; |
private ZoomManager mZoomManager; |
@@ -99,33 +161,77 @@ public class ContentView extends FrameLayout { |
AndroidBrowserProcess.initContentViewProcess(context, maxRendererProcesses); |
} |
- public ContentView(Context context, int nativeWebContents, int personality) { |
- this(context, nativeWebContents, null, android.R.attr.webViewStyle, personality); |
+ /** |
+ * Initialize the process as the platform browser. This must be called before accessing |
+ * ContentView in order to treat this as a Chromium browser process. |
+ * |
+ * @param context Context used to obtain the application context. |
+ * @param maxRendererProcesses Same as ContentView.enableMultiProcess() |
+ * @hide Only used by the platform browser. |
+ */ |
+ public static void initChromiumBrowserProcess(Context context, int maxRendererProcesses) { |
+ AndroidBrowserProcess.initChromiumBrowserProcess(context, maxRendererProcesses); |
} |
- private ContentView(Context context, int nativeWebContents, AttributeSet attrs, int defStyle, |
- int personality) { |
- super(context, attrs, defStyle); |
+ /** |
+ * Constructs a new ContentViewCore. |
+ * |
+ * @param context The context used to create this. |
+ * @param containerView The view that will act as a container for all views created by this. |
+ * @param internalDispatcher Handles dispatching all hidden or super methods to the |
+ * containerView. |
+ * @param nativeWebContents A pointer to the native web contents. |
+ * @param personality The type of ContentViewCore being created. |
+ */ |
+ public ContentViewCore( |
+ Context context, ViewGroup containerView, |
+ InternalAccessDelegate internalDispatcher, |
+ int nativeWebContents, int personality) { |
+ mContext = context; |
+ mContainerView = containerView; |
+ mContainerViewInternals = internalDispatcher; |
WeakContext.initializeWeakContext(context); |
// By default, ContentView will initialize single process mode. The call to |
// initContentViewProcess below is ignored if either the ContentView host called |
// enableMultiProcess() or the platform browser called initChromiumBrowserProcess(). |
- AndroidBrowserProcess.initContentViewProcess(context, MAX_RENDERERS_SINGLE_PROCESS); |
+ AndroidBrowserProcess.initContentViewProcess( |
+ context, AndroidBrowserProcess.MAX_RENDERERS_SINGLE_PROCESS); |
initialize(context, nativeWebContents, personality); |
} |
+ /** |
+ * @return The context used for creating this ContentViewCore. |
+ */ |
+ public Context getContext() { |
+ return mContext; |
+ } |
+ |
+ /** |
+ * @return The ViewGroup that all view actions of this ContentViewCore should interact with. |
+ */ |
+ protected ViewGroup getContainerView() { |
+ return mContainerView; |
+ } |
+ |
// TODO(jrg): incomplete; upstream the rest of this method. |
private void initialize(Context context, int nativeWebContents, int personality) { |
- mNativeContentView = nativeInit(nativeWebContents); |
+ mNativeContentViewCore = nativeInit(nativeWebContents); |
mPersonality = personality; |
- mContentSettings = new ContentSettings(this, mNativeContentView); |
- |
+ mContentSettings = new ContentSettings(this, mNativeContentViewCore); |
+ mContainerView.setWillNotDraw(false); |
+ mContainerView.setFocusable(true); |
+ mContainerView.setFocusableInTouchMode(true); |
+ if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) { |
+ mContainerView.setHorizontalScrollBarEnabled(false); |
+ mContainerView.setVerticalScrollBarEnabled(false); |
+ } |
+ mContainerView.setClickable(true); |
initGestureDetectors(context); |
- Log.i(TAG, "mNativeContentView=0x"+ Integer.toHexString(mNativeContentView)); |
+ Log.i(TAG, "mNativeContentView=0x"+ Integer.toHexString(mNativeContentViewCore)); |
} |
/** |
@@ -143,17 +249,15 @@ public class ContentView extends FrameLayout { |
} |
} |
- |
/** |
* Destroy the internal state of the WebView. This method may only be called |
* after the WebView has been removed from the view system. No other methods |
* may be called on this WebView after this method has been called. |
*/ |
- // TODO(jrg): incomplete; upstream the rest of this method. |
public void destroy() { |
- if (mNativeContentView != 0) { |
- nativeDestroy(mNativeContentView); |
- mNativeContentView = 0; |
+ if (mNativeContentViewCore != 0) { |
+ nativeDestroy(mNativeContentViewCore); |
+ mNativeContentViewCore = 0; |
} |
if (mContentSettings != null) { |
mContentSettings.destroy(); |
@@ -166,7 +270,18 @@ public class ContentView extends FrameLayout { |
* It is illegal to call any other public method after destroy(). |
*/ |
public boolean isAlive() { |
- return mNativeContentView != 0; |
+ return mNativeContentViewCore != 0; |
+ } |
+ |
+ /** |
+ * For internal use. Throws IllegalStateException if mNativeContentView is 0. |
+ * Use this to ensure we get a useful Java stack trace, rather than a native |
+ * crash dump, from use-after-destroy bugs in Java code. |
+ */ |
+ void checkIsAlive() throws IllegalStateException { |
+ if (!isAlive()) { |
+ throw new IllegalStateException("ContentView used after destroy() was called"); |
+ } |
} |
public void setContentViewClient(ContentViewClient client) { |
@@ -174,8 +289,8 @@ public class ContentView extends FrameLayout { |
throw new IllegalArgumentException("The client can't be null."); |
} |
mContentViewClient = client; |
- if (mNativeContentView != 0) { |
- nativeSetClient(mNativeContentView, mContentViewClient); |
+ if (mNativeContentViewCore != 0) { |
+ nativeSetClient(mNativeContentViewCore, mContentViewClient); |
} |
} |
@@ -214,10 +329,10 @@ public class ContentView extends FrameLayout { |
* omnibox can report suggestions correctly. |
*/ |
public void loadUrlWithoutUrlSanitization(String url, int pageTransition) { |
- if (mNativeContentView != 0) { |
+ if (mNativeContentViewCore != 0) { |
if (isPersonalityView()) { |
nativeLoadUrlWithoutUrlSanitizationWithUserAgentOverride( |
- mNativeContentView, |
+ mNativeContentViewCore, |
url, |
pageTransition, |
mContentSettings.getUserAgentString()); |
@@ -225,7 +340,7 @@ public class ContentView extends FrameLayout { |
// Chrome stores overridden UA strings in navigation history |
// items, so they stay the same on going back / forward. |
nativeLoadUrlWithoutUrlSanitization( |
- mNativeContentView, |
+ mNativeContentViewCore, |
url, |
pageTransition); |
} |
@@ -240,7 +355,7 @@ public class ContentView extends FrameLayout { |
* Stops loading the current web contents. |
*/ |
public void stopLoading() { |
- if (mNativeContentView != 0) nativeStopLoading(mNativeContentView); |
+ if (mNativeContentViewCore != 0) nativeStopLoading(mNativeContentViewCore); |
} |
/** |
@@ -249,7 +364,7 @@ public class ContentView extends FrameLayout { |
* @return The URL of the current page. |
*/ |
public String getUrl() { |
- if (mNativeContentView != 0) return nativeGetURL(mNativeContentView); |
+ if (mNativeContentViewCore != 0) return nativeGetURL(mNativeContentViewCore); |
return null; |
} |
@@ -259,7 +374,7 @@ public class ContentView extends FrameLayout { |
* @return The title of the current page. |
*/ |
public String getTitle() { |
- if (mNativeContentView != 0) return nativeGetTitle(mNativeContentView); |
+ if (mNativeContentViewCore != 0) return nativeGetTitle(mNativeContentViewCore); |
return null; |
} |
@@ -267,24 +382,32 @@ public class ContentView extends FrameLayout { |
* @return The load progress of current web contents (range is 0 - 100). |
*/ |
public int getProgress() { |
- if (mNativeContentView != 0) { |
- return (int) (100.0 * nativeGetLoadProgress(mNativeContentView)); |
+ if (mNativeContentViewCore != 0) { |
+ return (int) (100.0 * nativeGetLoadProgress(mNativeContentViewCore)); |
} |
return 100; |
} |
+ public int getWidth() { |
+ return mContainerView.getWidth(); |
+ } |
+ |
+ public int getHeight() { |
+ return mContainerView.getHeight(); |
+ } |
+ |
/** |
* @return Whether the current WebContents has a previous navigation entry. |
*/ |
public boolean canGoBack() { |
- return mNativeContentView != 0 && nativeCanGoBack(mNativeContentView); |
+ return mNativeContentViewCore != 0 && nativeCanGoBack(mNativeContentViewCore); |
} |
/** |
* @return Whether the current WebContents has a navigation entry after the current one. |
*/ |
public boolean canGoForward() { |
- return mNativeContentView != 0 && nativeCanGoForward(mNativeContentView); |
+ return mNativeContentViewCore != 0 && nativeCanGoForward(mNativeContentViewCore); |
} |
/** |
@@ -292,7 +415,7 @@ public class ContentView extends FrameLayout { |
* @return Whether we can move in history by given offset |
*/ |
public boolean canGoToOffset(int offset) { |
- return mNativeContentView != 0 && nativeCanGoToOffset(mNativeContentView, offset); |
+ return mNativeContentViewCore != 0 && nativeCanGoToOffset(mNativeContentViewCore, offset); |
} |
/** |
@@ -301,28 +424,28 @@ public class ContentView extends FrameLayout { |
* @param offset The offset into the navigation history. |
*/ |
public void goToOffset(int offset) { |
- if (mNativeContentView != 0) nativeGoToOffset(mNativeContentView, offset); |
+ if (mNativeContentViewCore != 0) nativeGoToOffset(mNativeContentViewCore, offset); |
} |
/** |
* Goes to the navigation entry before the current one. |
*/ |
public void goBack() { |
- if (mNativeContentView != 0) nativeGoBack(mNativeContentView); |
+ if (mNativeContentViewCore != 0) nativeGoBack(mNativeContentViewCore); |
} |
/** |
* Goes to the navigation entry following the current one. |
*/ |
public void goForward() { |
- if (mNativeContentView != 0) nativeGoForward(mNativeContentView); |
+ if (mNativeContentViewCore != 0) nativeGoForward(mNativeContentViewCore); |
} |
/** |
* Reload the current page. |
*/ |
public void reload() { |
- if (mNativeContentView != 0) nativeReload(mNativeContentView); |
+ if (mNativeContentViewCore != 0) nativeReload(mNativeContentViewCore); |
} |
/** |
@@ -330,14 +453,14 @@ public class ContentView extends FrameLayout { |
* directions. |
*/ |
public void clearHistory() { |
- if (mNativeContentView != 0) nativeClearHistory(mNativeContentView); |
+ if (mNativeContentViewCore != 0) nativeClearHistory(mNativeContentViewCore); |
} |
/** |
* Start pinch zoom. You must call {@link #pinchEnd} to stop. |
*/ |
void pinchBegin(long timeMs, int x, int y) { |
- if (mNativeContentView != 0) { |
+ if (mNativeContentViewCore != 0) { |
// TODO(tedchoc): Pass pinch begin to native. |
} |
} |
@@ -346,7 +469,7 @@ public class ContentView extends FrameLayout { |
* Stop pinch zoom. |
*/ |
void pinchEnd(long timeMs) { |
- if (mNativeContentView != 0) { |
+ if (mNativeContentViewCore != 0) { |
// TODO(tedchoc): Pass pinch end to native. |
} |
} |
@@ -368,7 +491,7 @@ public class ContentView extends FrameLayout { |
* coordinate. |
*/ |
void pinchBy(long timeMs, int anchorX, int anchorY, float delta) { |
- if (mNativeContentView != 0) { |
+ if (mNativeContentViewCore != 0) { |
// TODO(tedchoc): Pass pinch by to native. |
} |
} |
@@ -387,6 +510,23 @@ public class ContentView extends FrameLayout { |
return mContentSettings; |
} |
+ // End FrameLayout overrides. |
+ |
+ /** |
+ * @see View#awakenScrollBars(int, boolean) |
+ */ |
+ @SuppressWarnings("javadoc") |
+ protected boolean awakenScrollBars(int startDelay, boolean invalidate) { |
+ // For the default implementation of ContentView which draws the scrollBars on the native |
+ // side, calling this function may get us into a bad state where we keep drawing the |
+ // scrollBars, so disable it by always returning false. |
+ if (mContainerView.getScrollBarStyle() == View.SCROLLBARS_INSIDE_OVERLAY) { |
+ return false; |
+ } else { |
+ return mContainerViewInternals.super_awakenScrollBars(startDelay, invalidate); |
+ } |
+ } |
+ |
private void initGestureDetectors(final Context context) { |
try { |
TraceEvent.begin(); |
@@ -445,15 +585,15 @@ public class ContentView extends FrameLayout { |
* @return Whether the native ContentView has crashed. |
*/ |
public boolean isCrashed() { |
- if (mNativeContentView == 0) return false; |
- return nativeCrashed(mNativeContentView); |
+ if (mNativeContentViewCore == 0) return false; |
+ return nativeCrashed(mNativeContentViewCore); |
} |
/** |
* @return Whether a reload happens when this ContentView is activated. |
*/ |
public boolean needsReload() { |
- return mNativeContentView != 0 && nativeNeedsReload(mNativeContentView); |
+ return mNativeContentViewCore != 0 && nativeNeedsReload(mNativeContentViewCore); |
} |
/** |
@@ -491,7 +631,7 @@ public class ContentView extends FrameLayout { |
return false; |
} |
- if (mNativeContentView == 0) { |
+ if (mNativeContentViewCore == 0) { |
return false; |
} |
@@ -520,7 +660,7 @@ public class ContentView extends FrameLayout { |
return false; |
} |
- if (mNativeContentView == 0) { |
+ if (mNativeContentViewCore == 0) { |
return false; |
} |
@@ -554,55 +694,57 @@ public class ContentView extends FrameLayout { |
getContentViewClient().onStartContentIntent(getContext(), contentUrl); |
} |
+ // The following methods are implemented at native side. |
/** |
* Initialize the ContentView native side. |
* Should be called with a valid native WebContents. |
- * If nativeInitProcess is never called, the first time this method is called, nativeInitProcess |
- * will be called implicitly with the default settings. |
+ * If nativeInitProcess is never called, the first time this method is called, |
+ * nativeInitProcess will be called implicitly with the default settings. |
* @param webContentsPtr the ContentView does not create a new native WebContents and uses |
* the provided one. |
* @return a native pointer to the native ContentView object. |
*/ |
private native int nativeInit(int webContentsPtr); |
- private native void nativeDestroy(int nativeContentViewImpl); |
+ private native void nativeDestroy(int nativeContentViewCoreImpl); |
- private native void nativeLoadUrlWithoutUrlSanitization(int nativeContentViewImpl, |
+ private native void nativeLoadUrlWithoutUrlSanitization(int nativeContentViewCoreImpl, |
String url, int pageTransition); |
private native void nativeLoadUrlWithoutUrlSanitizationWithUserAgentOverride( |
- int nativeContentViewImpl, String url, int pageTransition, String userAgentOverride); |
+ int nativeContentViewCoreImpl, String url, int pageTransition, |
+ String userAgentOverride); |
- private native String nativeGetURL(int nativeContentViewImpl); |
+ private native String nativeGetURL(int nativeContentViewCoreImpl); |
- private native String nativeGetTitle(int nativeContentViewImpl); |
+ private native String nativeGetTitle(int nativeContentViewCoreImpl); |
- private native double nativeGetLoadProgress(int nativeContentViewImpl); |
+ private native double nativeGetLoadProgress(int nativeContentViewCoreImpl); |
- private native boolean nativeIsIncognito(int nativeContentViewImpl); |
+ private native boolean nativeIsIncognito(int nativeContentViewCoreImpl); |
// Returns true if the native side crashed so that java side can draw a sad tab. |
- private native boolean nativeCrashed(int nativeContentViewImpl); |
+ private native boolean nativeCrashed(int nativeContentViewCoreImpl); |
- private native boolean nativeCanGoBack(int nativeContentViewImpl); |
+ private native boolean nativeCanGoBack(int nativeContentViewCoreImpl); |
- private native boolean nativeCanGoForward(int nativeContentViewImpl); |
+ private native boolean nativeCanGoForward(int nativeContentViewCoreImpl); |
- private native boolean nativeCanGoToOffset(int nativeContentViewImpl, int offset); |
+ private native boolean nativeCanGoToOffset(int nativeContentViewCoreImpl, int offset); |
- private native void nativeGoToOffset(int nativeContentViewImpl, int offset); |
+ private native void nativeGoToOffset(int nativeContentViewCoreImpl, int offset); |
- private native void nativeGoBack(int nativeContentViewImpl); |
+ private native void nativeGoBack(int nativeContentViewCoreImpl); |
- private native void nativeGoForward(int nativeContentViewImpl); |
+ private native void nativeGoForward(int nativeContentViewCoreImpl); |
- private native void nativeStopLoading(int nativeContentViewImpl); |
+ private native void nativeStopLoading(int nativeContentViewCoreImpl); |
- private native void nativeReload(int nativeContentViewImpl); |
+ private native void nativeReload(int nativeContentViewCoreImpl); |
- private native void nativeSetClient(int nativeContentViewImpl, ContentViewClient client); |
+ private native void nativeSetClient(int nativeContentViewCoreImpl, ContentViewClient client); |
- private native boolean nativeNeedsReload(int nativeContentViewImpl); |
+ private native boolean nativeNeedsReload(int nativeContentViewCoreImpl); |
- private native void nativeClearHistory(int nativeContentViewImpl); |
+ private native void nativeClearHistory(int nativeContentViewCoreImpl); |
} |