summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/browser/aw_browser_context.cc13
-rw-r--r--android_webview/browser/aw_browser_context.h3
-rw-r--r--android_webview/browser/aw_content_browser_client.cc6
-rw-r--r--android_webview/browser/aw_content_browser_client.h2
-rw-r--r--android_webview/browser/browser_view_renderer.h3
-rw-r--r--android_webview/browser/in_process_view_renderer.cc36
-rw-r--r--android_webview/browser/in_process_view_renderer.h5
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java9
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwContents.java278
-rw-r--r--android_webview/java/src/org/chromium/android_webview/AwSettings.java97
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java9
-rw-r--r--android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java4
-rw-r--r--android_webview/native/aw_contents.cc133
-rw-r--r--android_webview/native/aw_contents.h32
-rw-r--r--android_webview/native/aw_settings.cc29
-rw-r--r--android_webview/native/aw_settings.h5
-rw-r--r--android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java10
-rw-r--r--content/browser/android/in_process/synchronous_input_event_filter.cc8
18 files changed, 350 insertions, 332 deletions
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index ea98457..958c66f 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -41,6 +41,8 @@ class AwResourceContext : public content::ResourceContext {
DISALLOW_COPY_AND_ASSIGN(AwResourceContext);
};
+AwBrowserContext* g_browser_context = NULL;
+
} // namespace
AwBrowserContext::AwBrowserContext(
@@ -48,9 +50,20 @@ AwBrowserContext::AwBrowserContext(
JniDependencyFactory* native_factory)
: context_storage_path_(path),
native_factory_(native_factory) {
+ DCHECK(g_browser_context == NULL);
+ g_browser_context = this;
}
AwBrowserContext::~AwBrowserContext() {
+ DCHECK(g_browser_context == this);
+ g_browser_context = NULL;
+}
+
+// static
+AwBrowserContext* AwBrowserContext::GetDefault() {
+ // TODO(joth): rather than store in a global here, lookup this instance
+ // from the Java-side peer.
+ return g_browser_context;
}
// static
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index b2f9178..b6a1134 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -46,6 +46,9 @@ class AwBrowserContext : public content::BrowserContext,
JniDependencyFactory* native_factory);
virtual ~AwBrowserContext();
+ // Currently only one instance per process is supported.
+ static AwBrowserContext* GetDefault();
+
// Convenience method to returns the AwBrowserContext corresponding to the
// given WebContents.
static AwBrowserContext* FromWebContents(
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index d41eccc..d58b8d7 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -29,8 +29,6 @@
namespace android_webview {
namespace {
-AwBrowserContext* g_browser_context;
-
class AwAccessTokenStore : public content::AccessTokenStore {
public:
AwAccessTokenStore() { }
@@ -67,7 +65,7 @@ std::string AwContentBrowserClient::GetAcceptLangsImpl() {
}
AwBrowserContext* AwContentBrowserClient::GetAwBrowserContext() {
- return g_browser_context;
+ return AwBrowserContext::GetDefault();
}
AwContentBrowserClient::AwContentBrowserClient(
@@ -79,11 +77,9 @@ AwContentBrowserClient::AwContentBrowserClient(
}
browser_context_.reset(
new AwBrowserContext(user_data_dir, native_factory_));
- g_browser_context = browser_context_.get();
}
AwContentBrowserClient::~AwContentBrowserClient() {
- g_browser_context = NULL;
}
void AwContentBrowserClient::AddCertificate(net::URLRequest* request,
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 5724efa..1ecd2f5 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -21,7 +21,7 @@ class AwContentBrowserClient : public content::ContentBrowserClient {
// This is what AwContentBrowserClient::GetAcceptLangs uses.
static std::string GetAcceptLangsImpl();
- // Returns the one AwBrowserContext for this process.
+ // Deprecated: use AwBrowserContext::GetDefault() instead.
static AwBrowserContext* GetAwBrowserContext();
AwContentBrowserClient(JniDependencyFactory* native_factory);
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index e24b25c..7d05aee 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -78,9 +78,6 @@ class BrowserViewRenderer {
static AwDrawSWFunctionTable* GetAwDrawSWFunctionTable();
static bool IsSkiaVersionCompatible();
- // Content control methods.
- virtual void SetContents(content::ContentViewCore* content_view_core) = 0;
-
// Rendering methods.
// Main handler for view drawing: performs a SW draw immediately, or sets up
diff --git a/android_webview/browser/in_process_view_renderer.cc b/android_webview/browser/in_process_view_renderer.cc
index 0ad4a41..e79591c 100644
--- a/android_webview/browser/in_process_view_renderer.cc
+++ b/android_webview/browser/in_process_view_renderer.cc
@@ -299,10 +299,11 @@ bool BrowserViewRenderer::IsSkiaVersionCompatible() {
InProcessViewRenderer::InProcessViewRenderer(
BrowserViewRenderer::Client* client,
- JavaHelper* java_helper)
+ JavaHelper* java_helper,
+ content::WebContents* web_contents)
: client_(client),
java_helper_(java_helper),
- web_contents_(NULL),
+ web_contents_(web_contents),
compositor_(NULL),
view_visible_(false),
continuous_invalidate_(false),
@@ -314,11 +315,18 @@ InProcessViewRenderer::InProcessViewRenderer(
hardware_failed_(false),
egl_context_at_init_(NULL),
weak_factory_(this) {
+ CHECK(web_contents_);
+ web_contents_->SetUserData(kUserDataKey, new UserData(this));
+ content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
+ // Currently the logic in this class relies on |compositor_| remaining NULL
+ // until the DidInitializeCompositor() call, hence it is not set here.
}
InProcessViewRenderer::~InProcessViewRenderer() {
- SetContents(NULL);
- DCHECK(compositor_ == NULL);
+ CHECK(web_contents_);
+ content::SynchronousCompositor::SetClientForWebContents(web_contents_, NULL);
+ web_contents_->SetUserData(kUserDataKey, NULL);
+ DCHECK(web_contents_ == NULL); // WebContentsGone should have been called.
}
// static
@@ -327,26 +335,6 @@ InProcessViewRenderer* InProcessViewRenderer::FromWebContents(
return UserData::GetInstance(contents);
}
-void InProcessViewRenderer::SetContents(
- content::ContentViewCore* content_view_core) {
- // First remove association from the prior ContentViewCore / WebContents.
- if (web_contents_) {
- content::SynchronousCompositor::SetClientForWebContents(web_contents_,
- NULL);
- web_contents_->SetUserData(kUserDataKey, NULL);
- DCHECK(!web_contents_); // WebContentsGone should have been called.
- }
-
- if (!content_view_core)
- return;
-
- web_contents_ = content_view_core->GetWebContents();
- web_contents_->SetUserData(kUserDataKey, new UserData(this));
- content::SynchronousCompositor::SetClientForWebContents(web_contents_, this);
- // Currently the logic in this class relies on |compositor_| remaining NULL
- // until the DidInitializeCompositor() call, hence it is not set here.
-}
-
void InProcessViewRenderer::WebContentsGone() {
web_contents_ = NULL;
compositor_ = NULL;
diff --git a/android_webview/browser/in_process_view_renderer.h b/android_webview/browser/in_process_view_renderer.h
index 55d5415b..d3e4166 100644
--- a/android_webview/browser/in_process_view_renderer.h
+++ b/android_webview/browser/in_process_view_renderer.h
@@ -26,15 +26,14 @@ class InProcessViewRenderer : public BrowserViewRenderer,
public content::SynchronousCompositorClient {
public:
InProcessViewRenderer(BrowserViewRenderer::Client* client,
- JavaHelper* java_helper);
+ JavaHelper* java_helper,
+ content::WebContents* web_contents);
virtual ~InProcessViewRenderer();
static InProcessViewRenderer* FromWebContents(
content::WebContents* contents);
// BrowserViewRenderer overrides
- virtual void SetContents(
- content::ContentViewCore* content_view_core) OVERRIDE;
virtual bool OnDraw(jobject java_canvas,
bool is_hardware_canvas,
const gfx::Point& scroll,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
index 2536d7b..9b0c987 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserContext.java
@@ -24,7 +24,14 @@ public class AwBrowserContext {
private AwGeolocationPermissions mGeolocationPermissions;
private AwCookieManager mCookieManager;
private AwFormDatabase mFormDatabase;
+ boolean mIsFileAccessGrantedByDefault;
+ public AwBrowserContext(SharedPreferences sharedPreferences,
+ boolean isFileAccessGrantedByDefault) {
+ mIsFileAccessGrantedByDefault = isFileAccessGrantedByDefault;
+ }
+
+ @Deprecated
public AwBrowserContext(SharedPreferences sharedPreferences) {
mSharedPreferences = sharedPreferences;
}
@@ -63,4 +70,4 @@ public class AwBrowserContext {
public void resumeTimers() {
ContentViewStatics.setWebKitSharedTimersSuspended(false);
}
-} \ No newline at end of file
+}
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 4730d24..9793b06 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -4,6 +4,7 @@
package org.chromium.android_webview;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -15,6 +16,7 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
+import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
@@ -107,19 +109,20 @@ public class AwContents {
}
private int mNativeAwContents;
- private AwBrowserContext mBrowserContext;
- private ViewGroup mContainerView;
+ private final AwBrowserContext mBrowserContext;
+ private final ViewGroup mContainerView;
private ContentViewCore mContentViewCore;
- private AwContentsClient mContentsClient;
- private AwContentsClientBridge mContentsClientBridge;
- private AwWebContentsDelegate mWebContentsDelegate;
- private AwContentsIoThreadClient mIoThreadClient;
- private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
- private InternalAccessDelegate mInternalAccessAdapter;
+ private final AwContentsClient mContentsClient;
+ private final AwContentsClientBridge mContentsClientBridge;
+ private final AwWebContentsDelegate mWebContentsDelegate;
+ private final AwContentsIoThreadClient mIoThreadClient;
+ private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
+ private final InternalAccessDelegate mInternalAccessAdapter;
private final AwLayoutSizer mLayoutSizer;
- private AwZoomControls mZoomControls;
+ private final AwZoomControls mZoomControls;
// This can be accessed on any thread after construction. See AwContentsIoThreadClient.
private final AwSettings mSettings;
+
private boolean mIsPaused;
private Bitmap mFavicon;
private boolean mHasRequestedVisitedHistoryFromClient;
@@ -127,7 +130,7 @@ public class AwContents {
private final double mDIPScale;
// Must call nativeUpdateLastHitTestData first to update this before use.
- private final HitTestData mPossiblyStaleHitTestData;
+ private final HitTestData mPossiblyStaleHitTestData = new HitTestData();
private DefaultVideoPosterRequestHandler mDefaultVideoPosterRequestHandler;
@@ -313,15 +316,24 @@ public class AwContents {
* @param containerView the view-hierarchy item this object will be bound to.
* @param internalAccessAdapter to access private methods on containerView.
* @param contentsClient will receive API callbacks from this WebView Contents
- * @param isAccessFromFileURLsGrantedByDefault passed to AwSettings.
*
* This constructor uses the default view sizing policy.
*/
public AwContents(AwBrowserContext browserContext, ViewGroup containerView,
+ InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient) {
+ this(browserContext, containerView, internalAccessAdapter, contentsClient,
+ new AwLayoutSizer());
+ }
+
+ // TODO(joth): Remove this overload when downstream no-longer passing
+ // isAccessFromFileURLsGrantedByDefault.
+ @Deprecated
+ public AwContents(AwBrowserContext browserContext, ViewGroup containerView,
InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient,
boolean isAccessFromFileURLsGrantedByDefault) {
this(browserContext, containerView, internalAccessAdapter, contentsClient,
- isAccessFromFileURLsGrantedByDefault, new AwLayoutSizer());
+ new AwLayoutSizer());
+ browserContext.mIsFileAccessGrantedByDefault = isAccessFromFileURLsGrantedByDefault;
}
private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView,
@@ -348,96 +360,130 @@ public class AwContents {
*/
public AwContents(AwBrowserContext browserContext, ViewGroup containerView,
InternalAccessDelegate internalAccessAdapter, AwContentsClient contentsClient,
- boolean isAccessFromFileURLsGrantedByDefault, AwLayoutSizer layoutSizer) {
+ AwLayoutSizer layoutSizer) {
mBrowserContext = browserContext;
mContainerView = containerView;
mInternalAccessAdapter = internalAccessAdapter;
- mDIPScale = DeviceDisplayInfo.create(containerView.getContext()).getDIPScale();
- // Note that ContentViewCore must be set up before AwContents, as ContentViewCore
- // setup performs process initialisation work needed by AwContents.
- mContentsClientBridge = new AwContentsClientBridge(contentsClient);
+ mContentsClient = contentsClient;
mLayoutSizer = layoutSizer;
+ mDIPScale = DeviceDisplayInfo.create(containerView.getContext()).getDIPScale();
mLayoutSizer.setDelegate(new AwLayoutSizerDelegate());
mLayoutSizer.setDIPScale(mDIPScale);
mWebContentsDelegate = new AwWebContentsDelegateAdapter(contentsClient,
mLayoutSizer.getPreferredSizeChangedListener());
- mNativeAwContents = nativeInit(mWebContentsDelegate, mContentsClientBridge);
- mContentsClient = contentsClient;
+ mContentsClientBridge = new AwContentsClientBridge(contentsClient);
+ mZoomControls = new AwZoomControls(this);
+ mIoThreadClient = new IoThreadClientImpl();
+ mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
+
+ boolean hasInternetPermission = containerView.getContext().checkPermission(
+ android.Manifest.permission.INTERNET,
+ Process.myPid(),
+ Process.myUid()) == PackageManager.PERMISSION_GRANTED;
+ AwSettings.ZoomSupportChangeListener zoomListener =
+ new AwSettings.ZoomSupportChangeListener() {
+ @Override
+ public void onMultiTouchZoomSupportChanged(boolean supportsMultiTouchZoom) {
+ mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoom);
+ }
+ };
+ mSettings = new AwSettings(hasInternetPermission, zoomListener,
+ mBrowserContext.mIsFileAccessGrantedByDefault, mDIPScale);
+ mDefaultVideoPosterRequestHandler = new DefaultVideoPosterRequestHandler(mContentsClient);
+ mSettings.setDefaultVideoPosterURL(
+ mDefaultVideoPosterRequestHandler.getDefaultVideoPosterURL());
+ mContentsClient.setDIPScale(mDIPScale);
+
+ setNewAwContents(nativeInit(browserContext));
+ }
+
+ /**
+ * Common initialization routine for adopting a native AwContents instance into this
+ * java instance.
+ *
+ * TAKE CARE! This method can get called multiple times per java instance. Code accordingly.
+ * ^^^^^^^^^ See the native class declaration for more details on relative object lifetimes.
+ */
+ private void setNewAwContents(int newAwContentsPtr) {
+ if (mNativeAwContents != 0) {
+ destroy();
+ mContentViewCore = null;
+ }
+
+ assert mNativeAwContents == 0 && mCleanupReference == null && mContentViewCore == null;
+
+ mNativeAwContents = newAwContentsPtr;
+ // TODO(joth): when the native and java counterparts of AwBrowserContext are hooked up to
+ // each other, we should update |mBrowserContext| according to the newly received native
+ // WebContent's browser context.
+
+ // The native side object has been bound to this java instance, so now is the time to
+ // bind all the native->java relationships.
mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));
int nativeWebContents = nativeGetWebContents(mNativeAwContents);
- mZoomControls = new AwZoomControls(this);
mContentViewCore = createAndInitializeContentViewCore(
- containerView, internalAccessAdapter, nativeWebContents,
+ mContainerView, mInternalAccessAdapter, nativeWebContents,
new AwPinchGestureStateListener(), mContentsClient.getContentViewClient(),
mZoomControls);
+ nativeSetJavaPeers(mNativeAwContents, this, mWebContentsDelegate, mContentsClientBridge,
+ mIoThreadClient, mInterceptNavigationDelegate);
mContentsClient.installWebContentsObserver(mContentViewCore);
+ mSettings.setWebContents(nativeWebContents);
+ }
- mSettings = new AwSettings(mContentViewCore.getContext(), nativeWebContents,
- mContentViewCore, isAccessFromFileURLsGrantedByDefault);
- setIoThreadClient(new IoThreadClientImpl());
- setInterceptNavigationDelegate(new InterceptNavigationDelegateImpl());
-
- mPossiblyStaleHitTestData = new HitTestData();
- nativeDidInitializeContentViewCore(mNativeAwContents,
- mContentViewCore.getNativeContentViewCore());
-
- mContentsClient.setDIPScale(mDIPScale);
- mSettings.setDIPScale(mDIPScale);
- mDefaultVideoPosterRequestHandler = new DefaultVideoPosterRequestHandler(mContentsClient);
- mSettings.setDefaultVideoPosterURL(
- mDefaultVideoPosterRequestHandler.getDefaultVideoPosterURL());
- }
-
- // Only valid within updatePhysicalBackingSizeIfNeeded().
- private final Rect mGlobalVisibleBoundsTemporary = new Rect();
-
- private void updatePhysicalBackingSizeIfNeeded() {
- // We musn't let the physical backing size get too big, otherwise we
- // will try to allocate a SurfaceTexture beyond what the GL driver can
- // cope with. In most cases, limiting the SurfaceTexture size to that
- // of the visible bounds of the WebView will be good enough i.e. the maximum
- // SurfaceTexture dimensions will match the screen dimensions).
- mContainerView.getGlobalVisibleRect(mGlobalVisibleBoundsTemporary);
- int width = mGlobalVisibleBoundsTemporary.width();
- int height = mGlobalVisibleBoundsTemporary.height();
- if (width != mLastGlobalVisibleWidth || height != mLastGlobalVisibleHeight) {
- mLastGlobalVisibleWidth = width;
- mLastGlobalVisibleHeight = height;
- mContentViewCore.onPhysicalBackingSizeChanged(width, height);
+ /**
+ * Called on the "source" AwContents that is opening the popup window to
+ * provide the AwContents to host the pop up content.
+ */
+ public void supplyContentsForPopup(AwContents newContents) {
+ int popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents);
+ if (popupNativeAwContents == 0) {
+ Log.w(TAG, "Popup WebView bind failed: no pending content.");
+ if (newContents != null) newContents.destroy();
+ return;
+ }
+ if (newContents == null) {
+ nativeDestroy(popupNativeAwContents);
+ return;
}
- }
-
- @VisibleForTesting
- public ContentViewCore getContentViewCore() {
- return mContentViewCore;
- }
- // Can be called from any thread.
- public AwSettings getSettings() {
- return mSettings;
+ newContents.receivePopupContents(popupNativeAwContents);
}
- public void setIoThreadClient(AwContentsIoThreadClient ioThreadClient) {
- mIoThreadClient = ioThreadClient;
- nativeSetIoThreadClient(mNativeAwContents, mIoThreadClient);
- }
+ // Recap: supplyContentsForPopup() is called on the parent window's content, this method is
+ // called on the popup window's content.
+ private void receivePopupContents(int popupNativeAwContents) {
+ setNewAwContents(popupNativeAwContents);
- private void setInterceptNavigationDelegate(InterceptNavigationDelegateImpl delegate) {
- mInterceptNavigationDelegate = delegate;
- nativeSetInterceptNavigationDelegate(mNativeAwContents, delegate);
+ // Finally refresh view size and visibility, to poke new values into ContentViewCore.
+ mLastGlobalVisibleWidth = 0;
+ mLastGlobalVisibleHeight = 0;
+ onSizeChanged(mContainerView.getWidth(), mContainerView.getHeight(), 0, 0);
+ updateVisiblityState();
+ onWindowFocusChanged(mWindowFocused);
}
public void destroy() {
mContentViewCore.destroy();
- // The native part of AwSettings isn't needed for the IoThreadClient instance.
- mSettings.destroy();
// We explicitly do not null out the mContentViewCore reference here
// because ContentViewCore already has code to deal with the case
// methods are called on it after it's been destroyed, and other
// code relies on AwContents.mContentViewCore to be non-null.
+
mCleanupReference.cleanupNow();
mNativeAwContents = 0;
+ mCleanupReference = null;
+ }
+
+ @VisibleForTesting
+ public ContentViewCore getContentViewCore() {
+ return mContentViewCore;
+ }
+
+ // Can be called from any thread.
+ public AwSettings getSettings() {
+ return mSettings;
}
public static void setAwDrawSWFunctionTable(int functionTablePointer) {
@@ -458,6 +504,29 @@ public class AwContents {
return nativeGetAwDrawGLViewContext(mNativeAwContents);
}
+ // Only valid within updatePhysicalBackingSizeIfNeeded().
+ private final Rect mGlobalVisibleBoundsTemporary = new Rect();
+
+ private void updatePhysicalBackingSizeIfNeeded() {
+ // We musn't let the physical backing size get too big, otherwise we
+ // will try to allocate a SurfaceTexture beyond what the GL driver can
+ // cope with. In most cases, limiting the SurfaceTexture size to that
+ // of the visible bounds of the WebView will be good enough i.e. the maximum
+ // SurfaceTexture dimensions will match the screen dimensions).
+ mContainerView.getGlobalVisibleRect(mGlobalVisibleBoundsTemporary);
+ int width = mGlobalVisibleBoundsTemporary.width();
+ int height = mGlobalVisibleBoundsTemporary.height();
+ if (width != mLastGlobalVisibleWidth || height != mLastGlobalVisibleHeight) {
+ mLastGlobalVisibleWidth = width;
+ mLastGlobalVisibleHeight = height;
+ mContentViewCore.onPhysicalBackingSizeChanged(width, height);
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // WebView[Provider] method implementations (where not provided by ContentViewCore)
+ //--------------------------------------------------------------------------------------------
+
// Only valid within onDraw().
private final Rect mClipBoundsTemporary = new Rect();
@@ -602,50 +671,6 @@ public class AwContents {
if (url == null || url.trim().isEmpty()) return null;
return url;
}
- /**
- * Called on the "source" AwContents that is opening the popup window to
- * provide the AwContents to host the pop up content.
- */
- public void supplyContentsForPopup(AwContents newContents) {
- int popupWebContents = nativeReleasePopupWebContents(mNativeAwContents);
- assert popupWebContents != 0;
- newContents.setNewWebContents(popupWebContents);
- }
-
- private void setNewWebContents(int newWebContentsPtr) {
- // When setting a new WebContents, we new up a ContentViewCore that will
- // wrap it and then swap it.
- ContentViewCore newCore = createAndInitializeContentViewCore(
- mContainerView, mInternalAccessAdapter, newWebContentsPtr,
- new AwPinchGestureStateListener(), mContentsClient.getContentViewClient(),
- mZoomControls);
- mContentsClient.installWebContentsObserver(newCore);
-
- // Now swap the Java side reference.
- mContentViewCore.destroy();
- mContentViewCore = newCore;
-
- // Now rewire native side to use the new WebContents.
- nativeSetWebContents(mNativeAwContents, newWebContentsPtr);
- nativeSetIoThreadClient(mNativeAwContents, mIoThreadClient);
- nativeSetInterceptNavigationDelegate(mNativeAwContents, mInterceptNavigationDelegate);
-
- // This will also apply settings to the new WebContents.
- mSettings.setWebContents(newWebContentsPtr);
-
- // Finally poke the new ContentViewCore with the size of the container view and show it.
- if (mContainerView.getWidth() != 0 || mContainerView.getHeight() != 0) {
- mContentViewCore.onSizeChanged(
- mContainerView.getWidth(), mContainerView.getHeight(), 0, 0);
- }
- nativeDidInitializeContentViewCore(mNativeAwContents,
- mContentViewCore.getNativeContentViewCore());
- if (mContainerView.getVisibility() == View.VISIBLE) {
- // The popup window was hidden when we prompted the embedder to display
- // it, so show it again now we have a container.
- mContentViewCore.onShow();
- }
- }
public void requestFocus() {
if (!mContainerView.isInTouchMode() && mSettings.shouldFocusFirstNode()) {
@@ -661,10 +686,6 @@ public class AwContents {
return mZoomControls.getZoomControlsViewForTest();
}
- //--------------------------------------------------------------------------------------------
- // WebView[Provider] method implementations (where not provided by ContentViewCore)
- //--------------------------------------------------------------------------------------------
-
/**
* @see ContentViewCore#getContentSettings()
*/
@@ -1425,26 +1446,22 @@ public class AwContents {
// Native methods
//--------------------------------------------------------------------------------------------
- private native int nativeInit(AwWebContentsDelegate webViewWebContentsDelegate,
- AwContentsClientBridge contentsClientBridge);
+ private static native int nativeInit(AwBrowserContext browserContext);
private static native void nativeDestroy(int nativeAwContents);
private static native void nativeSetAwDrawSWFunctionTable(int functionTablePointer);
private static native void nativeSetAwDrawGLFunctionTable(int functionTablePointer);
private static native int nativeGetAwDrawGLFunction();
-
+ private native void nativeSetJavaPeers(int nativeAwContents, AwContents awContents,
+ AwWebContentsDelegate webViewWebContentsDelegate,
+ AwContentsClientBridge contentsClientBridge,
+ AwContentsIoThreadClient ioThreadClient,
+ InterceptNavigationDelegate navigationInterceptionDelegate);
private native int nativeGetWebContents(int nativeAwContents);
- private native void nativeDidInitializeContentViewCore(int nativeAwContents,
- int nativeContentViewCore);
private native void nativeDocumentHasImages(int nativeAwContents, Message message);
private native void nativeGenerateMHTML(
int nativeAwContents, String path, ValueCallback<String> callback);
- private native void nativeSetIoThreadClient(int nativeAwContents,
- AwContentsIoThreadClient ioThreadClient);
- private native void nativeSetInterceptNavigationDelegate(int nativeAwContents,
- InterceptNavigationDelegate navigationInterceptionDelegate);
-
private native void nativeAddVisitedLinks(int nativeAwContents, String[] visitedLinks);
private native boolean nativeOnDraw(int nativeAwContents, Canvas canvas,
boolean isHardwareAccelerated, int scrollX, int ScrollY,
@@ -1471,8 +1488,7 @@ public class AwContents {
// Returns false if restore state fails.
private native boolean nativeRestoreFromOpaqueState(int nativeAwContents, byte[] state);
- private native int nativeReleasePopupWebContents(int nativeAwContents);
- private native void nativeSetWebContents(int nativeAwContents, int nativeNewWebContents);
+ private native int nativeReleasePopupAwContents(int nativeAwContents);
private native void nativeFocusFirstNode(int nativeAwContents);
private native int nativeGetAwDrawGLViewContext(int nativeAwContents);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
index 2be4d46..0f3ddc2 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwSettings.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
@@ -4,12 +4,9 @@
package org.chromium.android_webview;
-import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.Process;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebSettings;
import android.webkit.WebView;
@@ -43,12 +40,14 @@ public class AwSettings {
// used from any thread. Internally, the class uses a message queue
// to call native code on the UI thread only.
+ // Values passed in on construction.
+ private final boolean mHasInternetPermission;
+ private final ZoomSupportChangeListener mZoomChangeListener;
+ private final double mDIPScale;
+
// Lock to protect all settings.
private final Object mAwSettingsLock = new Object();
- private final Context mContext;
- private double mDIPScale;
-
private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
private int mTextSizePercent = 100;
private String mStandardFontFamily = "sans-serif";
@@ -94,6 +93,7 @@ public class AwSettings {
private boolean mSupportZoom = true;
private boolean mBuiltInZoomControls = false;
private boolean mDisplayZoomControls = true;
+
static class LazyDefaultUserAgent{
// Lazy Holder pattern
private static final String sInstance = nativeGetDefaultUserAgent();
@@ -106,11 +106,9 @@ public class AwSettings {
// client.
private static boolean sAppCachePathIsSet = false;
- // The native side of this object.
+ // The native side of this object. It's lifetime is bounded by the WebContent it is attached to.
private int mNativeAwSettings = 0;
- private ContentViewCore mContentViewCore;
-
// A flag to avoid sending superfluous synchronization messages.
private boolean mIsUpdateWebkitPrefsMessagePending = false;
// Custom handler that queues messages to call native code on the UI thread.
@@ -166,44 +164,39 @@ public class AwSettings {
}
}
- public AwSettings(Context context,
- int nativeWebContents,
- ContentViewCore contentViewCore,
- boolean isAccessFromFileURLsGrantedByDefault) {
- ThreadUtils.assertOnUiThread();
- mContext = context;
- mBlockNetworkLoads = mContext.checkPermission(
- android.Manifest.permission.INTERNET,
- Process.myPid(),
- Process.myUid()) != PackageManager.PERMISSION_GRANTED;
- mContentViewCore = contentViewCore;
- mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoomLocked());
+ interface ZoomSupportChangeListener {
+ public void onMultiTouchZoomSupportChanged(boolean supportsMultiTouchZoom);
+ }
- if (isAccessFromFileURLsGrantedByDefault) {
- mAllowUniversalAccessFromFileURLs = true;
- mAllowFileAccessFromFileURLs = true;
- }
+ public AwSettings(boolean hasInternetPermission,
+ ZoomSupportChangeListener zoomChangeListener,
+ boolean isAccessFromFileURLsGrantedByDefault,
+ double dipScale) {
+ ThreadUtils.assertOnUiThread();
+ synchronized (mAwSettingsLock) {
+ mHasInternetPermission = hasInternetPermission;
+ mZoomChangeListener = zoomChangeListener;
+ mDIPScale = dipScale;
+ mEventHandler = new EventHandler();
+ mBlockNetworkLoads = !hasInternetPermission;
- mEventHandler = new EventHandler();
- mUserAgent = LazyDefaultUserAgent.sInstance;
+ if (isAccessFromFileURLsGrantedByDefault) {
+ mAllowUniversalAccessFromFileURLs = true;
+ mAllowFileAccessFromFileURLs = true;
+ }
- synchronized (mAwSettingsLock) {
- mNativeAwSettings = nativeInit(nativeWebContents);
+ mUserAgent = LazyDefaultUserAgent.sInstance;
+ onMultiTouchZoomSupportChanged(supportsMultiTouchZoomLocked());
}
- assert mNativeAwSettings != 0;
+ // Defer initializing the native side until a native WebContents instance is set.
}
- public void destroy() {
- nativeDestroy(mNativeAwSettings);
+ @CalledByNative
+ private void nativeAwSettingsGone(int nativeAwSettings) {
+ assert mNativeAwSettings != 0 && mNativeAwSettings == nativeAwSettings;
mNativeAwSettings = 0;
}
- public void setDIPScale(double dipScale) {
- synchronized (mAwSettingsLock) {
- mDIPScale = dipScale;
- }
- }
-
@CalledByNative
private double getDIPScaleLocked() {
return mDIPScale;
@@ -211,7 +204,14 @@ public class AwSettings {
public void setWebContents(int nativeWebContents) {
synchronized (mAwSettingsLock) {
- nativeSetWebContentsLocked(mNativeAwSettings, nativeWebContents);
+ if (mNativeAwSettings != 0) {
+ nativeDestroy(mNativeAwSettings);
+ assert mNativeAwSettings == 0; // nativeAwSettingsGone should have been called.
+ }
+ if (nativeWebContents != 0) {
+ mNativeAwSettings = nativeInit(nativeWebContents);
+ nativeUpdateEverythingLocked(mNativeAwSettings);
+ }
}
}
@@ -220,10 +220,7 @@ public class AwSettings {
*/
public void setBlockNetworkLoads(boolean flag) {
synchronized (mAwSettingsLock) {
- if (!flag && mContext.checkPermission(
- android.Manifest.permission.INTERNET,
- Process.myPid(),
- Process.myUid()) != PackageManager.PERMISSION_GRANTED) {
+ if (!flag && !mHasInternetPermission) {
throw new SecurityException("Permission denied - " +
"application missing INTERNET permission");
}
@@ -1239,11 +1236,12 @@ public class AwSettings {
return mDefaultVideoPosterURL;
}
- private void updateMultiTouchZoomSupport(final boolean supportsMultiTouchZoom) {
- ThreadUtils.runOnUiThreadBlocking(new Runnable() {
+ private void onMultiTouchZoomSupportChanged(final boolean supportsMultiTouchZoom) {
+ // Always post asynchronously here, to avoid doubling back onto the caller.
+ ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
- mContentViewCore.updateMultiTouchZoomSupport(supportsMultiTouchZoom);
+ mZoomChangeListener.onMultiTouchZoomSupportChanged(supportsMultiTouchZoom);
}
});
}
@@ -1255,7 +1253,7 @@ public class AwSettings {
synchronized (mAwSettingsLock) {
if (mSupportZoom != support) {
mSupportZoom = support;
- updateMultiTouchZoomSupport(supportsMultiTouchZoomLocked());
+ onMultiTouchZoomSupportChanged(supportsMultiTouchZoomLocked());
}
}
}
@@ -1276,7 +1274,7 @@ public class AwSettings {
synchronized (mAwSettingsLock) {
if (mBuiltInZoomControls != enabled) {
mBuiltInZoomControls = enabled;
- updateMultiTouchZoomSupport(supportsMultiTouchZoomLocked());
+ onMultiTouchZoomSupportChanged(supportsMultiTouchZoomLocked());
}
}
}
@@ -1309,6 +1307,7 @@ public class AwSettings {
}
private boolean supportsMultiTouchZoomLocked() {
+ assert Thread.holdsLock(mAwSettingsLock);
return mSupportZoom && mBuiltInZoomControls;
}
@@ -1353,8 +1352,6 @@ public class AwSettings {
private native void nativeResetScrollAndScaleState(int nativeAwSettings);
- private native void nativeSetWebContentsLocked(int nativeAwSettings, int nativeWebContents);
-
private native void nativeUpdateEverythingLocked(int nativeAwSettings);
private native void nativeUpdateInitialPageScaleLocked(int nativeAwSettings);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
index 69a2c50a..3bdeb31 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwTestBase.java
@@ -217,14 +217,17 @@ public class AwTestBase
return testContainerView;
}
+ // The browser context needs to be a process-wide singleton.
+ private AwBrowserContext mBrowserContext =
+ new AwBrowserContext(new InMemorySharedPreferences(), false);
+
protected AwTestContainerView createDetachedAwTestContainerView(
final AwContentsClient awContentsClient,
final TestDependencyFactory testDependencyFactory) {
final AwTestContainerView testContainerView = new AwTestContainerView(getActivity());
testContainerView.initialize(new AwContents(
- new AwBrowserContext(new InMemorySharedPreferences()),
- testContainerView, testContainerView.getInternalAccessDelegate(),
- awContentsClient, false, testDependencyFactory.createLayoutSizer()));
+ mBrowserContext, testContainerView, testContainerView.getInternalAccessDelegate(),
+ awContentsClient, testDependencyFactory.createLayoutSizer()));
return testContainerView;
}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
index 1f36e68..76d2265 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
@@ -58,9 +58,9 @@ public class LoadUrlTest extends AwTestBase {
@SmallTest
@Feature({"AndroidWebView"})
public void testDataUrlCharset() throws Throwable {
- // Note that the '£' is the important character in the following
+ // Note that the \u00a3 (pound sterling) is the important character in the following
// string as it's not in the US_ASCII character set.
- final String expectedTitle = "You win £100!";
+ final String expectedTitle = "You win \u00a3100!";
final String data =
"<html><head><title>" + expectedTitle + "</title></head><body>foo</body></html>";
final TestAwContentsClient contentsClient = new TestAwContentsClient();
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 8d726da..142f413 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -79,7 +79,11 @@ namespace android_webview {
namespace {
-static JavaBrowserViewRendererHelper java_renderer_helper;
+JavaBrowserViewRendererHelper* java_renderer_helper() {
+ static JavaBrowserViewRendererHelper* g_instance
+ = new JavaBrowserViewRendererHelper;
+ return g_instance;
+}
const void* kAwContentsUserDataKey = &kAwContentsUserDataKey;
@@ -118,38 +122,15 @@ AwContents* AwContents::FromID(int render_process_id, int render_view_id) {
return FromWebContents(web_contents);
}
-AwContents::AwContents(JNIEnv* env,
- jobject obj,
- jobject web_contents_delegate,
- jobject contents_client_bridge)
- : java_ref_(env, obj),
- web_contents_delegate_(
- new AwWebContentsDelegate(env, web_contents_delegate)),
- contents_client_bridge_(
- new AwContentsClientBridge(env, contents_client_bridge)),
+AwContents::AwContents(scoped_ptr<WebContents> web_contents)
+ : web_contents_(web_contents.Pass()),
browser_view_renderer_(
- new InProcessViewRenderer(this, &java_renderer_helper)) {
- android_webview::AwBrowserDependencyFactory* dependency_factory =
- android_webview::AwBrowserDependencyFactory::GetInstance();
-
- // TODO(joth): rather than create and set the WebContents here, expose the
- // factory method to java side and have that orchestrate the construction
- // order.
- SetWebContents(dependency_factory->CreateWebContents());
-}
-
-void AwContents::SetWebContents(content::WebContents* web_contents) {
- web_contents_.reset(web_contents);
- if (find_helper_.get()) {
- find_helper_->SetListener(NULL);
- }
+ new InProcessViewRenderer(this, java_renderer_helper(),
+ web_contents_.get())) {
icon_helper_.reset(new IconHelper(web_contents_.get()));
icon_helper_->SetListener(this);
web_contents_->SetUserData(kAwContentsUserDataKey,
new AwContentsUserData(this));
- AwContentsClientBridgeBase::Associate(web_contents_.get(),
- contents_client_bridge_.get());
- web_contents_->SetDelegate(web_contents_delegate_.get());
render_view_host_ext_.reset(
new AwRenderViewHostExt(this, web_contents_.get()));
@@ -160,6 +141,40 @@ void AwContents::SetWebContents(content::WebContents* web_contents) {
InitAutofillIfNecessary(autofill_manager_delegate->GetSaveFormData());
}
+void AwContents::SetJavaPeers(JNIEnv* env,
+ jobject obj,
+ jobject aw_contents,
+ jobject web_contents_delegate,
+ jobject contents_client_bridge,
+ jobject io_thread_client,
+ jobject intercept_navigation_delegate) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // The |aw_content| param is technically spurious as it duplicates |obj| but
+ // is passed over anyway to make the binding more explicit.
+ java_ref_ = JavaObjectWeakGlobalRef(env, aw_contents);
+
+ web_contents_delegate_.reset(
+ new AwWebContentsDelegate(env, web_contents_delegate));
+ web_contents_->SetDelegate(web_contents_delegate_.get());
+
+ contents_client_bridge_.reset(
+ new AwContentsClientBridge(env, contents_client_bridge));
+ AwContentsClientBridgeBase::Associate(web_contents_.get(),
+ contents_client_bridge_.get());
+
+ AwContentsIoThreadClientImpl::Associate(
+ web_contents_.get(), ScopedJavaLocalRef<jobject>(env, io_thread_client));
+ int child_id = web_contents_->GetRenderProcessHost()->GetID();
+ int route_id = web_contents_->GetRoutingID();
+ AwResourceDispatcherHostDelegate::OnIoThreadClientReady(child_id, route_id);
+
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ InterceptNavigationDelegate::Associate(
+ web_contents_.get(),
+ make_scoped_ptr(new InterceptNavigationDelegate(
+ env, intercept_navigation_delegate)));
+}
+
void AwContents::SetSaveFormData(bool enabled) {
InitAutofillIfNecessary(enabled);
// We need to check for the existence, since autofill_manager_delegate
@@ -196,10 +211,6 @@ void AwContents::InitAutofillIfNecessary(bool enabled) {
AutofillExternalDelegate::FromWebContents(web_contents));
}
-void AwContents::SetWebContents(JNIEnv* env, jobject obj, jint new_wc) {
- SetWebContents(reinterpret_cast<content::WebContents*>(new_wc));
-}
-
AwContents::~AwContents() {
DCHECK(AwContents::FromWebContents(web_contents_.get()) == this);
web_contents_->RemoveUserData(kAwContentsUserDataKey);
@@ -210,34 +221,35 @@ AwContents::~AwContents() {
}
jint AwContents::GetWebContents(JNIEnv* env, jobject obj) {
+ DCHECK(web_contents_);
return reinterpret_cast<jint>(web_contents_.get());
}
-void AwContents::DidInitializeContentViewCore(JNIEnv* env, jobject obj,
- jint content_view_core) {
- ContentViewCore* core = reinterpret_cast<ContentViewCore*>(content_view_core);
- DCHECK(core == ContentViewCore::FromWebContents(web_contents_.get()));
- browser_view_renderer_->SetContents(core);
-}
-
void AwContents::Destroy(JNIEnv* env, jobject obj) {
delete this;
}
-// static
-void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
+static jint Init(JNIEnv* env, jclass, jobject browser_context) {
+ // TODO(joth): Use |browser_context| to get the native BrowserContext, rather
+ // than hard-code the default instance lookup here.
+ scoped_ptr<WebContents> web_contents(content::WebContents::Create(
+ content::WebContents::CreateParams(AwBrowserContext::GetDefault())));
+ // Return an 'uninitialized' instance; most work is deferred until the
+ // subsequent SetJavaPeers() call.
+ return reinterpret_cast<jint>(new AwContents(web_contents.Pass()));
+}
+
+static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
BrowserViewRenderer::SetAwDrawSWFunctionTable(
reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
}
-// static
-void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, jint function_table) {
+static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, jint function_table) {
GpuMemoryBufferImpl::SetAwDrawGLFunctionTable(
reinterpret_cast<AwDrawGLFunctionTable*>(function_table));
}
-// static
-jint GetAwDrawGLFunction(JNIEnv* env, jclass) {
+static jint GetAwDrawGLFunction(JNIEnv* env, jclass) {
return reinterpret_cast<jint>(&DrawGLFunction);
}
@@ -306,24 +318,6 @@ bool AwContents::OnReceivedHttpAuthRequest(const JavaRef<jobject>& handler,
return true;
}
-void AwContents::SetIoThreadClient(JNIEnv* env, jobject obj, jobject client) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AwContentsIoThreadClientImpl::Associate(
- web_contents_.get(), ScopedJavaLocalRef<jobject>(env, client));
- int child_id = web_contents_->GetRenderProcessHost()->GetID();
- int route_id = web_contents_->GetRoutingID();
- AwResourceDispatcherHostDelegate::OnIoThreadClientReady(child_id, route_id);
-}
-
-void AwContents::SetInterceptNavigationDelegate(JNIEnv* env,
- jobject obj,
- jobject delegate) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- InterceptNavigationDelegate::Associate(
- web_contents_.get(),
- make_scoped_ptr(new InterceptNavigationDelegate(env, delegate)));
-}
-
void AwContents::AddVisitedLinks(JNIEnv* env,
jobject obj,
jobjectArray jvisited_links) {
@@ -343,15 +337,6 @@ void AwContents::AddVisitedLinks(JNIEnv* env,
->AddVisitedURLs(visited_link_gurls);
}
-static jint Init(JNIEnv* env,
- jobject obj,
- jobject web_contents_delegate,
- jobject contents_client_bridge) {
- AwContents* tab = new AwContents(env, obj, web_contents_delegate,
- contents_client_bridge);
- return reinterpret_cast<jint>(tab);
-}
-
bool RegisterAwContents(JNIEnv* env) {
return RegisterNativesImpl(env) >= 0;
}
@@ -673,14 +658,14 @@ void AwContents::SetPendingWebContentsForPopup(
base::MessageLoop::current()->DeleteSoon(FROM_HERE, pending.release());
return;
}
- pending_contents_ = pending.Pass();
+ pending_contents_.reset(new AwContents(pending.Pass()));
}
void AwContents::FocusFirstNode(JNIEnv* env, jobject obj) {
web_contents_->FocusThroughTabTraversal(false);
}
-jint AwContents::ReleasePopupWebContents(JNIEnv* env, jobject obj) {
+jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) {
return reinterpret_cast<jint>(pending_contents_.release());
}
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 170e9b7..1189e9f 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -36,6 +36,15 @@ class AwWebContentsDelegate;
// Provides the ownership of and access to browser components required for
// WebView functionality; analogous to chrome's TabContents, but with a
// level of indirection provided by the AwContentsContainer abstraction.
+//
+// Object lifetime:
+// For most purposes the java and native objects can be considered to have
+// 1:1 lifetime and relationship. The exception is the java instance that
+// hosts a popup will be rebound to a second native instance (carrying the
+// popup content) and discard the 'default' native instance it made on
+// construction. A native instance is only bound to at most one Java peer over
+// its entire lifetime - see Init() and SetPendingWebContentsForPopup() for the
+// construction points, and SetJavaPeers() where these paths join.
class AwContents : public FindHelper::Listener,
public IconHelper::Listener,
public AwRenderViewHostExtClient,
@@ -48,10 +57,7 @@ class AwContents : public FindHelper::Listener,
// render_process_id and render_view_id, or NULL.
static AwContents* FromID(int render_process_id, int render_view_id);
- AwContents(JNIEnv* env,
- jobject obj,
- jobject web_contents_delegate,
- jobject contents_client_bridge);
+ AwContents(scoped_ptr<content::WebContents> web_contents);
virtual ~AwContents();
AwRenderViewHostExt* render_view_host_ext() {
@@ -67,18 +73,19 @@ class AwContents : public FindHelper::Listener,
const std::string& realm);
// Methods called from Java.
+ void SetJavaPeers(JNIEnv* env,
+ jobject obj,
+ jobject aw_contents,
+ jobject web_contents_delegate,
+ jobject contents_client_bridge,
+ jobject io_thread_client,
+ jobject intercept_navigation_delegate);
jint GetWebContents(JNIEnv* env, jobject obj);
- void SetWebContents(JNIEnv* env, jobject obj, jint web_contents);
jint GetAwContentsClientBridge(JNIEnv* env, jobject obj);
- void DidInitializeContentViewCore(JNIEnv* env, jobject obj,
- jint content_view_core);
void Destroy(JNIEnv* env, jobject obj);
void DocumentHasImages(JNIEnv* env, jobject obj, jobject message);
void GenerateMHTML(JNIEnv* env, jobject obj, jstring jpath, jobject callback);
- void SetIoThreadClient(JNIEnv* env, jobject obj, jobject client);
- void SetInterceptNavigationDelegate(JNIEnv* env, jobject obj,
- jobject delegate);
void AddVisitedLinks(JNIEnv* env, jobject obj, jobjectArray jvisited_links);
base::android::ScopedJavaLocalRef<jbyteArray> GetCertificate(
JNIEnv* env, jobject obj);
@@ -145,12 +152,11 @@ class AwContents : public FindHelper::Listener,
void ClearCache(JNIEnv* env, jobject obj, jboolean include_disk_files);
void SetPendingWebContentsForPopup(scoped_ptr<content::WebContents> pending);
- jint ReleasePopupWebContents(JNIEnv* env, jobject obj);
+ jint ReleasePopupAwContents(JNIEnv* env, jobject obj);
void SetSaveFormData(bool enabled);
private:
- void SetWebContents(content::WebContents* web_contents);
void InitAutofillIfNecessary(bool enabled);
JavaObjectWeakGlobalRef java_ref_;
@@ -160,7 +166,7 @@ class AwContents : public FindHelper::Listener,
scoped_ptr<AwRenderViewHostExt> render_view_host_ext_;
scoped_ptr<FindHelper> find_helper_;
scoped_ptr<IconHelper> icon_helper_;
- scoped_ptr<content::WebContents> pending_contents_;
+ scoped_ptr<AwContents> pending_contents_;
scoped_ptr<BrowserViewRenderer> browser_view_renderer_;
// GURL is supplied by the content layer as requesting frame.
diff --git a/android_webview/native/aw_settings.cc b/android_webview/native/aw_settings.cc
index 8d44487..15c60aa 100644
--- a/android_webview/native/aw_settings.cc
+++ b/android_webview/native/aw_settings.cc
@@ -24,11 +24,19 @@ using base::android::ScopedJavaLocalRef;
namespace android_webview {
-AwSettings::AwSettings(JNIEnv* env, jobject obj)
- : aw_settings_(env, obj) {
+AwSettings::AwSettings(JNIEnv* env, jobject obj, jint web_contents)
+ : WebContentsObserver(
+ reinterpret_cast<content::WebContents*>(web_contents)),
+ aw_settings_(env, obj) {
}
AwSettings::~AwSettings() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
+ jobject obj = scoped_obj.obj();
+ if (!obj) return;
+ Java_AwSettings_nativeAwSettingsGone(env, obj,
+ reinterpret_cast<jint>(this));
}
void AwSettings::Destroy(JNIEnv* env, jobject obj) {
@@ -48,15 +56,6 @@ void AwSettings::ResetScrollAndScaleState(JNIEnv* env, jobject obj) {
rvhe->ResetScrollAndScaleState();
}
-void AwSettings::SetWebContentsLocked(
- JNIEnv* env, jobject obj, jint jweb_contents) {
- content::WebContents* web_contents =
- reinterpret_cast<content::WebContents*>(jweb_contents);
- Observe(web_contents);
-
- UpdateEverythingLocked(env, obj);
-}
-
void AwSettings::UpdateEverything() {
JNIEnv* env = base::android::AttachCurrentThread();
CHECK(env);
@@ -250,12 +249,14 @@ void AwSettings::RenderViewCreated(content::RenderViewHost* render_view_host) {
UpdateEverything();
}
-// Assumed to be called from the Java object's constructor, thus is "Locked".
+void AwSettings::WebContentsDestroyed(content::WebContents* web_contents) {
+ delete this;
+}
+
static jint Init(JNIEnv* env,
jobject obj,
jint web_contents) {
- AwSettings* settings = new AwSettings(env, obj);
- settings->SetWebContentsLocked(env, obj, web_contents);
+ AwSettings* settings = new AwSettings(env, obj, web_contents);
return reinterpret_cast<jint>(settings);
}
diff --git a/android_webview/native/aw_settings.h b/android_webview/native/aw_settings.h
index 4d0d5a0..d547f34 100644
--- a/android_webview/native/aw_settings.h
+++ b/android_webview/native/aw_settings.h
@@ -18,14 +18,13 @@ class AwRenderViewHostExt;
class AwSettings : public content::WebContentsObserver {
public:
- AwSettings(JNIEnv* env, jobject obj);
+ AwSettings(JNIEnv* env, jobject obj, jint web_contents);
virtual ~AwSettings();
// Called from Java. Methods with "Locked" suffix require that the settings
// access lock is held during their execution.
void Destroy(JNIEnv* env, jobject obj);
void ResetScrollAndScaleState(JNIEnv* env, jobject obj);
- void SetWebContentsLocked(JNIEnv* env, jobject obj, jint web_contents);
void UpdateEverythingLocked(JNIEnv* env, jobject obj);
void UpdateInitialPageScaleLocked(JNIEnv* env, jobject obj);
void UpdateUserAgentLocked(JNIEnv* env, jobject obj);
@@ -40,6 +39,8 @@ class AwSettings : public content::WebContentsObserver {
// WebContentsObserver overrides:
virtual void RenderViewCreated(
content::RenderViewHost* render_view_host) OVERRIDE;
+ virtual void WebContentsDestroyed(
+ content::WebContents* web_contents) OVERRIDE;
JavaObjectWeakGlobalRef aw_settings_;
};
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
index e2d6dcf..5646bc1 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
@@ -39,6 +39,7 @@ import org.chromium.content.browser.LoadUrlParams;
public class AwShellActivity extends Activity {
private final static String PREFERENCES_NAME = "AwShellPrefs";
private final static String INITIAL_URL = "about:blank";
+ private AwBrowserContext mBrowserContext;
private AwTestContainerView mAwTestContainerView;
private EditText mUrlTextView;
private ImageButton mPrevButton;
@@ -83,11 +84,12 @@ public class AwShellActivity extends Activity {
SharedPreferences sharedPreferences =
getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
- AwBrowserContext browserContext = new AwBrowserContext(sharedPreferences);
-
- testContainerView.initialize(new AwContents(browserContext, testContainerView,
+ if (mBrowserContext == null) {
+ mBrowserContext = new AwBrowserContext(sharedPreferences, false);
+ }
+ testContainerView.initialize(new AwContents(mBrowserContext, testContainerView,
testContainerView.getInternalAccessDelegate(),
- awContentsClient, false));
+ awContentsClient));
testContainerView.getAwContents().getSettings().setJavaScriptEnabled(true);
return testContainerView;
}
diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc
index 30f96a2..57ee7d9 100644
--- a/content/browser/android/in_process/synchronous_input_event_filter.cc
+++ b/content/browser/android/in_process/synchronous_input_event_filter.cc
@@ -47,8 +47,12 @@ void SynchronousInputEventFilter::SetBoundHandlerOnUIThread(
void SynchronousInputEventFilter::DidAddInputHandler(
int routing_id,
cc::InputHandler* input_handler) {
- SynchronousCompositorImpl::FromRoutingID(routing_id)
- ->SetInputHandler(input_handler);
+ // The SynchronusCompositorImpl can be NULL if the WebContents that it's
+ // bound to has already been deleted.
+ SynchronousCompositorImpl* compositor =
+ SynchronousCompositorImpl::FromRoutingID(routing_id);
+ if (compositor)
+ compositor->SetInputHandler(input_handler);
}
void SynchronousInputEventFilter::DidRemoveInputHandler(int routing_id) {