是否可以在onCreateWindow创建的WebView上调用addJavascriptInterface?

时间:2014-02-27 06:20:09

标签: android android-webview chromium webviewclient

我有一个简单的浏览器应用,我的onCreateWindow看起来像这样:

if (userGesture) {
            WebView childView = new WebView(webBrowserActivity);
            WebSettings settings = childView.getSettings();
            settings.setJavaScriptEnabled(true);
            settings.setSupportZoom(true);
            settings.setJavaScriptCanOpenWindowsAutomatically(true);
            settings.setBuiltInZoomControls(true);
            settings.setSupportMultipleWindows(true);
            settings.setLoadWithOverviewMode(true);
            settings.setUseWideViewPort(true);
            childView.addJavascriptInterface(new MyInterface(),"NAME");
            <--- code in here to add the view to a ViewPager.
            WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
            transport.setWebView(childView);
            resultMsg.sendToTarget();
            Log.v(TAG, "Opening popup for " + childView.getUrl());
            webBrowserActivity.invalidateOptionsMenu();
            return true;
        } else {
            return false;
        }

我稍后尝试添加此界面,我也尝试在页面加载后调用reload()loadUrl(),因为文档说明必须在加载之前添加javascript界面这页纸。这些都没有帮助。有人做过这个吗?

感谢。

编辑:我应该提一下我在4.4上看到的更多内容,我正在使用Chrome的桌面调试器,我可以进入控制台,在第一个webview上看到window.NAME对象而不是第二个。在4.3它似乎经常工作。

我编辑了上面的代码以显示我正在使用的设置。我添加到WebView的javascript接口在添加到Activity启动时创建的第一个WebView时工作得很好。

4 个答案:

答案 0 :(得分:2)

不幸的是,KitKat WebView中存在一个错误,无法在弹出窗口中注册JavaScript界面​​。我担心的问题没有已知的解决方法,除了你的建议,保留弹出窗口的URL,从onCreateWindow返回false,然后创建一个全新的webview并将弹出URL加载到其中。

答案 1 :(得分:0)

是。它应该工作。我希望你这样做:

mWebView.getSettings().setJavaScriptEnabled(true);

答案 2 :(得分:0)

在onCreateWindow创建的webview之后,我遇到了同样的问题。 在挖掘资源后,我觉得这是不可能的。

final WebView.WebViewTransport transport = (WebView.WebViewTransport) msg.obj;
if(transport!=null){
    transport.setWebView(mCustomWebView);
}
msg.sendToTarget();

我们向目标发送消息后,WebViewChromium执行此操作

        mUiThreadHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case NEW_WEBVIEW_CREATED:
                    WebView.WebViewTransport t = (WebView.WebViewTransport) msg.obj;
                    WebView newWebView = t.getWebView();
                    if (newWebView == mWebView) {
                        throw new IllegalArgumentException(
                                "Parent WebView cannot host it's own popup window. Please " +
                                "use WebSettings.setSupportMultipleWindows(false)");
                    }

                    if (newWebView != null && newWebView.copyBackForwardList().getSize() != 0) {
                        throw new IllegalArgumentException(
                                "New WebView for popup window must not have been previously " +
                                "navigated.");
                    }

                    **WebViewChromium.completeWindowCreation(mWebView, newWebView);**
                    break;
                default:
                    throw new IllegalStateException();
            }
        }

然后,它会读到addPossiblyUnsafeJavascriptInterface

public void addPossiblyUnsafeJavascriptInterface(Object object, String name,
        Class<? extends Annotation> requiredAnnotation) {
    if (mNativeContentViewCore != 0 && object != null) {
        mJavaScriptInterfaces.put(name, object);
        nativeAddJavascriptInterface(mNativeContentViewCore, object, name, requiredAnnotation,
                mRetainedJavaScriptObjects);
    }
}

出于安全原因,似乎阻止onCreateWindow在webview上添加JS。

评论说

  

/ **        *此方法将提供的Java对象注入ContentViewCore。        *该对象被注入到主框架的JavaScript上下文中,        *使用提供的名称。这允许从中访问Java对象        * JavaScript。请注意,注入的对象不会出现        * JavaScript直到下一页(重新)加载。例如:        *

 view.addJavascriptInterface(new Object(), "injectedObject");
     * view.loadData("", "text/html", null);
     * view.loadUrl("javascript:alert(injectedObject.toString())");
       *

重要提示:        *

           *
  • addJavascriptInterface()可用于允许JavaScript控制        *主机应用程序。这是一个强大的功能,但也提出了一个        * 安全风险。在包含的ContentViewCore中使用此方法        *不受信任的内容可能允许攻击者操纵主机        *以非预期的方式应用程序,使用权限执行Java代码        *主机应用程序。在a中使用此方法时要特别小心        * ContentViewCore,可能包含不受信任的内容。特别小心        *应该采取措施,以避免无意中访问继承的方法,如        *作为{@link Object#getClass()}。要阻止访问继承的方法,        *传递{@code requiredAnnotation}的注释。这将确保        *只有{@code requiredAnnotation}的方法才会暴露给        * Javascript图层。 {@code requiredAnnotation}将传递给所有人        *如果任何方法返回一个对象,则随后注入Java对象。这个        *表示适用相同的限制(或缺少限制)。或者,        * {@link #addJavascriptInterface(Object,String)}可以被调用,其中        *自动使用{@link JavascriptInterface}注释。        *
  • JavaScript与私有背景上的Java对象进行交互        * ContentViewCore的主题。因此需要注意保养        *线程安全。
  •        *

有一个两难的境地。您可以通过从在CreateWindow上创建的webview获取URL并使用url创建新的webview来使用JS。我试过,当链接是简单的超链接时,它工作。但是通过这种方式,一些页面,尤其是通过javascript打开的页面,无法正常工作。

到目前为止,我得到了这个,而且我的时间不够。请有人分享更多。感谢。

答案 3 :(得分:-3)

方法addJavascriptInterface有一个安全警告:

  

仅适用于针对API级别JELLY_BEAN_MR1及更高版本的应用程序   使用JavascriptInterface注释的公共方法可以是   从JavaScript访问。

所以,如果你真的需要它,你的代码应该是这样的:

@JavascriptInterface
public void yourJavaFunction() 
{
    //do you stuff
}

请注意,通过这样做,您将面临安全风险,如note中所述。