summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsteveblock@chromium.org <steveblock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 14:35:16 +0000
committersteveblock@chromium.org <steveblock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-30 14:35:16 +0000
commit40a724c19088d15440019a1132ba1ab3780be086 (patch)
tree9ccf2d95f1010666c91ec593153f8c022fd88130
parentc1965eac99f5406588a109d178f0eda22240049a (diff)
downloadchromium_src-40a724c19088d15440019a1132ba1ab3780be086.zip
chromium_src-40a724c19088d15440019a1132ba1ab3780be086.tar.gz
chromium_src-40a724c19088d15440019a1132ba1ab3780be086.tar.bz2
Hook up ContentViewCore.add/removeJavascriptInterface()
The entry point to the Java Bridge is JavaBridgeDispatcherHostManager. This is not part of the content API so is available only on WebContentsImpl, not WebContents. We therefore modify ContentViewCoreImpl to store and use WebContentsImpl*, rather than WebContents*. It's safe for ContentViewCoreImpl to cast the WebContents* it receives in its constructor to WebContentsImpl* because WebContentsImpl is the only concrete implementation of the WebContents interface. BUG=110637 Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=148945 Review URL: https://chromiumcodereview.appspot.com/9192008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148951 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/android/content_view_core_impl.cc29
-rw-r--r--content/browser/android/content_view_core_impl.h11
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java59
3 files changed, 96 insertions, 3 deletions
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 21d3bd7..fd1ab9b 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -10,6 +10,8 @@
#include "base/android/scoped_java_ref.h"
#include "content/browser/android/content_view_client.h"
#include "content/browser/android/touch_point.h"
+#include "content/browser/renderer_host/java/java_bound_object.h"
+#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
@@ -18,11 +20,13 @@
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/web_contents.h"
#include "jni/ContentViewCore_jni.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/android/WebInputEventFactory.h"
#include "webkit/glue/webmenuitem.h"
using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::GetClass;
@@ -72,7 +76,7 @@ ContentViewCore* ContentViewCore::GetNativeContentViewCore(JNIEnv* env,
ContentViewCoreImpl::ContentViewCoreImpl(JNIEnv* env, jobject obj,
WebContents* web_contents)
- : web_contents_(web_contents),
+ : web_contents_(static_cast<WebContentsImpl*>(web_contents)),
tab_crashed_(false) {
DCHECK(web_contents) <<
"A ContentViewCoreImpl should be created with a valid WebContents.";
@@ -313,6 +317,29 @@ void ContentViewCoreImpl::SetClient(JNIEnv* env, jobject obj, jobject jclient) {
content_view_client_.swap(client);
}
+void ContentViewCoreImpl::AddJavascriptInterface(
+ JNIEnv* env,
+ jobject /* obj */,
+ jobject object,
+ jstring name,
+ jboolean allow_inherited_methods) {
+ ScopedJavaLocalRef<jobject> scoped_object(env, object);
+ // JavaBoundObject creates the NPObject with a ref count of 1, and
+ // JavaBridgeDispatcherHostManager takes its own ref.
+ NPObject* bound_object = JavaBoundObject::Create(scoped_object,
+ allow_inherited_methods);
+ web_contents_->java_bridge_dispatcher_host_manager()->AddNamedObject(
+ ConvertJavaStringToUTF16(env, name), bound_object);
+ WebKit::WebBindings::releaseObject(bound_object);
+}
+
+void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
+ jobject /* obj */,
+ jstring name) {
+ web_contents_->java_bridge_dispatcher_host_manager()->RemoveNamedObject(
+ ConvertJavaStringToUTF16(env, name));
+}
+
// --------------------------------------------------------------------------
// Methods called from native code
// --------------------------------------------------------------------------
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 796c148..704725a 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -14,6 +14,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/notification_observer.h"
#include "googleurl/src/gurl.h"
@@ -33,6 +34,8 @@ class ContentViewCoreImpl : public ContentViewCore,
ContentViewCoreImpl(JNIEnv* env,
jobject obj,
WebContents* web_contents);
+
+ // ContentViewCore overrides
virtual void Destroy(JNIEnv* env, jobject obj) OVERRIDE;
// --------------------------------------------------------------------------
@@ -108,6 +111,12 @@ class ContentViewCoreImpl : public ContentViewCore,
jboolean NeedsReload(JNIEnv* env, jobject obj);
void ClearHistory(JNIEnv* env, jobject obj);
void SetClient(JNIEnv* env, jobject obj, jobject jclient);
+ void AddJavascriptInterface(JNIEnv* env,
+ jobject obj,
+ jobject object,
+ jstring name,
+ jboolean allow_inherited_methods);
+ void RemoveJavascriptInterface(JNIEnv* env, jobject obj, jstring name);
// --------------------------------------------------------------------------
// Public methods that call to Java via JNI
@@ -186,7 +195,7 @@ class ContentViewCoreImpl : public ContentViewCore,
// Reference to the current WebContents used to determine how and what to
// display in the ContentViewCore.
- WebContents* web_contents_;
+ WebContentsImpl* web_contents_;
// We only set this to be the delegate of the web_contents if we own it.
scoped_ptr<ContentViewClient> content_view_client_;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index ee08d3a..1d6364b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -130,7 +130,7 @@ public class ContentViewCore implements MotionEventDelegate {
private ContentSettings mContentSettings;
- // Native pointer to C++ ContentView object which will be set by nativeInit()
+ // Native pointer to C++ ContentViewCoreImpl object which will be set by nativeInit().
private int mNativeContentViewCore = 0;
private ContentViewGestureHandler mContentViewGestureHandler;
@@ -854,6 +854,58 @@ public class ContentViewCore implements MotionEventDelegate {
return mZoomManager.getZoomControlsViewForTest();
}
+ /**
+ * This method injects the supplied Java object into the ContentViewCore.
+ * The object is injected into the JavaScript context of the main frame,
+ * using the supplied name. This allows the Java object to be accessed from
+ * JavaScript. Note that that injected objects will not appear in
+ * JavaScript until the page is next (re)loaded. For example:
+ * <pre> view.addJavascriptInterface(new Object(), "injectedObject");
+ * view.loadData("<!DOCTYPE html><title></title>", "text/html", null);
+ * view.loadUrl("javascript:alert(injectedObject.toString())");</pre>
+ * <p><strong>IMPORTANT:</strong>
+ * <ul>
+ * <li> addJavascriptInterface() can be used to allow JavaScript to control
+ * the host application. This is a powerful feature, but also presents a
+ * security risk. Use of this method in a ContentViewCore containing
+ * untrusted content could allow an attacker to manipulate the host
+ * application in unintended ways, executing Java code with the permissions
+ * of the host application. Use extreme care when using this method in a
+ * ContentViewCore which could contain untrusted content. Particular care
+ * should be taken to avoid unintentional access to inherited methods, such
+ * as {@link Object#getClass()}. To prevent access to inherited methods,
+ * set {@code allowInheritedMethods} to {@code false}. In addition, ensure
+ * that the injected object's public methods return only objects designed
+ * to be used by untrusted code, and never return a raw Object instance.
+ * <li> JavaScript interacts with Java objects on a private, background
+ * thread of the ContentViewCore. Care is therefore required to maintain
+ * thread safety.</li>
+ * </ul></p>
+ *
+ * @param object The Java object to inject into the ContentViewCore's
+ * JavaScript context. Null values are ignored.
+ * @param name The name used to expose the instance in JavaScript.
+ * @param allowInheritedMethods Whether or not inherited methods may be
+ * called from JavaScript.
+ */
+ public void addJavascriptInterface(Object object, String name, boolean allowInheritedMethods) {
+ if (mNativeContentViewCore != 0 && object != null) {
+ nativeAddJavascriptInterface(mNativeContentViewCore, object, name,
+ allowInheritedMethods);
+ }
+ }
+
+ /**
+ * Removes a previously added JavaScript interface with the given name.
+ *
+ * @param name The name of the interface to remove.
+ */
+ public void removeJavascriptInterface(String name) {
+ if (mNativeContentViewCore != 0) {
+ nativeRemoveJavascriptInterface(mNativeContentViewCore, name);
+ }
+ }
+
@CalledByNative
private void startContentIntent(String contentUrl) {
getContentViewClient().onStartContentIntent(getContext(), contentUrl);
@@ -948,4 +1000,9 @@ public class ContentViewCore implements MotionEventDelegate {
private native boolean nativeNeedsReload(int nativeContentViewCoreImpl);
private native void nativeClearHistory(int nativeContentViewCoreImpl);
+
+ private native void nativeAddJavascriptInterface(int nativeContentViewCoreImpl, Object object,
+ String name, boolean allowInheritedMethods);
+
+ private native void nativeRemoveJavascriptInterface(int nativeContentViewCoreImpl, String name);
}