将JavaScript注入框架

时间:2018-11-16 20:48:37

标签: javascript android inject

我有一个Android应用程序(一个Web浏览器),它使用默认的Webview加载网页。通过重载shouldInterceptRequest方法,我使用OkHTTP3库加载页面。

之所以这样做,是因为我想在执行任何Javascript之前将JavaScript注入每个页面。使用evaluateJavascript无法做到这一点,因为它是异步的,因此不能保证将首先执行代码。这是它的代码:

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
    val httpRequestBuilder = Request.Builder()

    when (request.method) {
        "GET" -> httpRequestBuilder.get()
    }

    httpRequestBuilder.url(url)
    httpRequestBuilder.headers(Headers.of(request.requestHeaders))

    val httpRequest = httpRequestBuilder.build()
    val httpResponse = OkHttpClient().newCall(httpRequest).execute()
    httpResponse?.run {
        val contentType = body()?.contentType()
        val mime = contentType?.type() + "/" + contentType?.subtype()
        val encoding = contentType?.charset()?.name() ?: "utf-8"
        val message = if (message().isEmpty()) {
            "OK"
        } else {
            message()
        }
        val header = HashMap<String, String>()
        headers().toMultimap().forEach { entry ->
            header[entry.key] = entry.value[0]
        }
         val contentStream = if (contentType?.subtype() == "html") {
            object : InputStream() {
                val streams = arrayOf(
                    ByteArrayInputStream("<script type=\"text/javascript\">".toByteArray()),
                    context.assets.open("MyJS.js"),
                    ByteArrayInputStream("</script>".toByteArray()),
                    body()?.byteStream()!!
                )
                var currentIndex = 0
                override fun read(): Int {
                    while (currentIndex < streams.size) {
                        val res = streams[currentIndex].read()
                        if (res != -1) {
                            return res
                        }
                        currentIndex++;
                    }
                    return -1;
                }
            }
        } else {
            body()?.byteStream()!!
        }

        return WebResourceResponse(mime, encoding, code(), message, header, contentStream)
}

注入的JavaScript本质上修改了一些原型。它还尝试将自身插入页面上的框架和iframe中以进行相同的修改。这是脚本自身的一部分:

(function() {
    var self = document.currentScript;
    var observer = new window.MutationObserver(function (changes) {
        for (var index = 0; index < changes.length; index++) {
            var change = changes[index];
            if (change.type == "childList") {
                for (var i = 0; i < change.addedNodes.length; i++) {
                    var node = change.addedNodes[i];
                    switch (node.nodeName) {
                        case "IFRAME":
                            var orig_sandbox = node.sandbox;
                            node.sandbox = "allow-scripts";
                            node.contentDocument.write("<script type=\"text/javascript\">" + self.text + "<\\/script>");
                            node.sandbox = orig_sandbox;
                            break;
                        case "FRAME":
                            node.contentDocument.write("<script type=\"text/javascript\">" + self.text + "<\\/script>");
                    }
                }
            }
        }
    });
    observer.observe(document.documentElement, {childList: true, subtree: true});
})();

目标是将此JavaScript注入未从网络加载的框架中(无论如何,这些框架都将由shouldInterceptRequest方法处理),而不是未从网络加载或由其他JavaScript创建的框架中。

现在我有一个问题,那就是它不起作用。它没有注入子帧中。

有人知道有可能将Javascript注入此类框架吗?

0 个答案:

没有答案