Внедрить JavaScript во фреймы - PullRequest
0 голосов
/ 16 ноября 2018

У меня есть приложение Android (веб-браузер), которое использует веб-представление по умолчанию для загрузки веб-страниц. Перегружая метод 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 существенно модифицирует некоторые прототипы. Также он пытается внедрить себя в фреймы и фреймы на странице, чтобы сделать те же изменения. Это часть скрипта, которая внедряет себя:

(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 в такие фреймы?

...