summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelim Gurun <sgurun@google.com>2012-09-04 16:45:53 -0700
committerSelim Gurun <sgurun@google.com>2012-10-05 10:07:29 -0700
commit66019c85693ec026e3826eb4b9a519a716f8594e (patch)
tree9f9dccd871003168b70ce33c4ddf3fb098ee0452
parent154feb1e6a05cad89e2fe0ee188071b280c5f3e9 (diff)
downloadbase-66019c85693ec026e3826eb4b9a519a716f8594e.tar.gz
DO NOT MERGE Control access to inherited methods of jsinterface objects
Bug: 7073422 Create the plumbing to use an annotation to allow access to inherited methods of jsinterface objects. The default webview behavior has not changed yet. However internally an a flag is introduced to restrict javascript access to methods that have an annotation. Change-Id: I0d8091da9b0aaecc0519863cf92b1fec2385da97
-rw-r--r--core/java/android/webkit/BrowserFrame.java50
-rw-r--r--core/java/android/webkit/JavascriptInterface.java33
-rw-r--r--core/java/android/webkit/WebView.java50
-rw-r--r--core/java/android/webkit/WebViewCore.java3
4 files changed, 116 insertions, 20 deletions
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index bb86269404b4..43e87960969a 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -87,8 +87,19 @@ class BrowserFrame extends Handler {
// Is this frame the main frame?
private boolean mIsMainFrame;
+ // Javascript interface object
+ private class JSObject {
+ Object object;
+ boolean requireAnnotation;
+
+ public JSObject(Object object, boolean requireAnnotation) {
+ this.object = object;
+ this.requireAnnotation = requireAnnotation;
+ }
+ }
+
// Attached Javascript interfaces
- private Map<String, Object> mJavaScriptObjects;
+ private Map<String, JSObject> mJavaScriptObjects;
private Set<Object> mRemovedJavaScriptObjects;
// Key store handler when Chromium HTTP stack is used.
@@ -232,10 +243,8 @@ class BrowserFrame extends Handler {
}
sConfigCallback.addHandler(this);
- mJavaScriptObjects = javascriptInterfaces;
- if (mJavaScriptObjects == null) {
- mJavaScriptObjects = new HashMap<String, Object>();
- }
+ mJavaScriptObjects = new HashMap<String, JSObject>();
+ addJavaScriptObjects(javascriptInterfaces);
mRemovedJavaScriptObjects = new HashSet<Object>();
mSettings = settings;
@@ -603,15 +612,32 @@ class BrowserFrame extends Handler {
Iterator<String> iter = mJavaScriptObjects.keySet().iterator();
while (iter.hasNext()) {
String interfaceName = iter.next();
- Object object = mJavaScriptObjects.get(interfaceName);
- if (object != null) {
+ JSObject jsobject = mJavaScriptObjects.get(interfaceName);
+ if (jsobject != null && jsobject.object != null) {
nativeAddJavascriptInterface(nativeFramePointer,
- mJavaScriptObjects.get(interfaceName), interfaceName);
+ jsobject.object, interfaceName, jsobject.requireAnnotation);
}
}
mRemovedJavaScriptObjects.clear();
}
+ /*
+ * Add javascript objects to the internal list of objects. The default behavior
+ * is to allow access to inherited methods (no annotation needed). This is only
+ * used when js objects are passed through a constructor (via a hidden constructor).
+ */
+ private void addJavaScriptObjects(Map<String, Object> javascriptInterfaces) {
+ if (javascriptInterfaces == null) return;
+ Iterator<String> iter = javascriptInterfaces.keySet().iterator();
+ while (iter.hasNext()) {
+ String interfaceName = iter.next();
+ Object object = javascriptInterfaces.get(interfaceName);
+ if (object != null) {
+ mJavaScriptObjects.put(interfaceName, new JSObject(object, false));
+ }
+ }
+ }
+
/**
* This method is called by WebCore to check whether application
* wants to hijack url loading
@@ -629,11 +655,11 @@ class BrowserFrame extends Handler {
}
}
- public void addJavascriptInterface(Object obj, String interfaceName) {
+ public void addJavascriptInterface(Object obj, String interfaceName,
+ boolean requireAnnotation) {
assert obj != null;
removeJavascriptInterface(interfaceName);
-
- mJavaScriptObjects.put(interfaceName, obj);
+ mJavaScriptObjects.put(interfaceName, new JSObject(obj, requireAnnotation));
}
public void removeJavascriptInterface(String interfaceName) {
@@ -1344,7 +1370,7 @@ class BrowserFrame extends Handler {
* Add a javascript interface to the main frame.
*/
private native void nativeAddJavascriptInterface(int nativeFramePointer,
- Object obj, String interfaceName);
+ Object obj, String interfaceName, boolean requireAnnotation);
/**
* Enable or disable the native cache.
diff --git a/core/java/android/webkit/JavascriptInterface.java b/core/java/android/webkit/JavascriptInterface.java
new file mode 100644
index 000000000000..a5312a2c0bf0
--- /dev/null
+++ b/core/java/android/webkit/JavascriptInterface.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation that allows exposing methods to JavaScript.
+ *
+ * @hide
+ */
+@SuppressWarnings("javadoc")
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface JavascriptInterface {
+} \ No newline at end of file
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5c833e4d920e..bb029e6a9a75 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -428,6 +428,40 @@ public class WebView extends AbsoluteLayout
}
+ /**
+ * A wrapper around text to speech.
+ */
+ private static class TextToSpeechWrapper {
+ private TextToSpeech mTextToSpeech;
+ public TextToSpeechWrapper(Context context) {
+ final String pkgName = context.getPackageName();
+ mTextToSpeech = new TextToSpeech(context, null, null, pkgName + ".**webview**");
+ }
+
+ @JavascriptInterface
+ @SuppressWarnings("unused")
+ public boolean isSpeaking() {
+ return mTextToSpeech.isSpeaking();
+ }
+
+ @JavascriptInterface
+ @SuppressWarnings("unused")
+ public int speak(String text, int queueMode, HashMap<String, String> params) {
+ return mTextToSpeech.speak(text, queueMode, params);
+ }
+
+ @JavascriptInterface
+ @SuppressWarnings("unused")
+ public int stop() {
+ return mTextToSpeech.stop();
+ }
+
+ @SuppressWarnings("unused")
+ protected void shutdown() {
+ mTextToSpeech.shutdown();
+ }
+ }
+
// A final CallbackProxy shared by WebViewCore and BrowserFrame.
private final CallbackProxy mCallbackProxy;
@@ -865,7 +899,7 @@ public class WebView extends AbsoluteLayout
private static final String PATTERN_MATCH_AXS_URL_PARAMETER = "(\\?axs=(0|1))|(&axs=(0|1))";
// TextToSpeech instance exposed to JavaScript to the injected screenreader.
- private TextToSpeech mTextToSpeech;
+ private TextToSpeechWrapper mTextToSpeech;
// variable to cache the above pattern in case accessibility is enabled.
private Pattern mMatchAxsUrlParameterPattern;
@@ -1308,12 +1342,8 @@ public class WebView extends AbsoluteLayout
// exposing the TTS for now ...
final Context ctx = getContext();
if (ctx != null) {
- final String packageName = ctx.getPackageName();
- if (packageName != null) {
- mTextToSpeech = new TextToSpeech(getContext(), null, null,
- packageName + ".**webview**");
- addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
- }
+ mTextToSpeech = new TextToSpeechWrapper(ctx);
+ addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE, true);
}
}
}
@@ -4110,6 +4140,11 @@ public class WebView extends AbsoluteLayout
* JavaScript.
*/
public void addJavascriptInterface(Object obj, String interfaceName) {
+ addJavascriptInterface(obj, interfaceName, false);
+ }
+
+ private void addJavascriptInterface(Object obj, String interfaceName,
+ boolean requireAnnotation) {
checkThread();
if (obj == null) {
return;
@@ -4117,6 +4152,7 @@ public class WebView extends AbsoluteLayout
WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
arg.mObject = obj;
arg.mInterfaceName = interfaceName;
+ arg.mRequireAnnotation = requireAnnotation;
mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 2d15afb5ba46..361d676120de 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -755,6 +755,7 @@ public final class WebViewCore {
static class JSInterfaceData {
Object mObject;
String mInterfaceName;
+ boolean mRequireAnnotation;
}
static class JSKeyData {
@@ -1411,7 +1412,7 @@ public final class WebViewCore {
case ADD_JS_INTERFACE:
JSInterfaceData jsData = (JSInterfaceData) msg.obj;
mBrowserFrame.addJavascriptInterface(jsData.mObject,
- jsData.mInterfaceName);
+ jsData.mInterfaceName, jsData.mRequireAnnotation);
break;
case REMOVE_JS_INTERFACE: