diff options
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); } |