龙空技术网

Jcef例子5_任意 script 执行之前被调用指定的js

程序猿阿乐 434

前言:

今天姐妹们对“js一个方法执行完执行另一个方法”都比较讲究,兄弟们都想要分析一些“js一个方法执行完执行另一个方法”的相关知识。那么小编也在网上收集了一些关于“js一个方法执行完执行另一个方法””的相关资讯,希望各位老铁们能喜欢,朋友们快快来了解一下吧!

在puppeteer中的实现

实现类似在puppeteer中,page.evaluateOnNewDocument(pageFunction[, ...args]) 。指定的函数在所属的页面被创建并且所属页面的任意 script 执行之前被调用。常用于修改页面js环境。

下面是在页面加载前重写 navigator.languages 属性的例子:

preload.js:

// 重写 `languages` 属性,使其用一个新的get方法Object.defineProperty(navigator, "languages", {  get: function() {    return ["en-US", "en", "bn"];  }});
// 假设 preload.js 和当前的代码在同一个目录const preloadFile = fs.readFileSync('./preload.js', 'utf8');await page.evaluateOnNewDocument(preloadFile);
在jcef中的实现

同puppeteer有所不同,由于jcef中executeJavaScript是异步的,为确保注入成功(在页面的js执行前执行),sleep一定时间。

准备个html

定义一个html,其中有个变量injectDataJcef5,如果展示的是html中的原始值,说明注入失败:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>测试打开静态文件</title></head><body>    <h1>测试sendMessage2Java+inject</h1>    <button onclick="globalVar.f.sendMessage2Java(injectDataJcef5)">sendInject</button>    <script>        var injectDataJcef5 = injectDataJcef5 || "无数据";        if(injectDataJcef5 == "无数据"){            alert('注入失败!');            throw new Error("注入失败!");        }        var globalVar = globalVar || {};        globalVar.f = globalVar.f || {}        globalVar.v = globalVar.v || {}        globalVar.v.fieldNm_fQuery = 'fQuery';        globalVar.v.fieldNm_fQueryCancel = 'fQueryCancel';        globalVar.f.parseUrlParamObj = function(){            // 1. 获取URL中的所有参数            const urlSearchParams = new URLSearchParams(window.location.search);            // 2. 定义一个空对象来存储参数            const params = {};            // 3. 遍历参数并将其添加到对象中            for (const [key, value] of urlSearchParams.entries()) {                params[key] = value;            }            // 4. 返回参数对象            return params;        }        const urlParamObj = globalVar.f.parseUrlParamObj();        if(urlParamObj.hasOwnProperty(globalVar.v.fieldNm_fQuery)){            urlParamObj[globalVar.v.fieldNm_fQuery];        }else{            throw new Error("未找到参数【" + globalVar.v.fieldNm_fQuery + "】");        }        if(urlParamObj.hasOwnProperty(globalVar.v.fieldNm_fQueryCancel)){            urlParamObj[globalVar.v.fieldNm_fQueryCancel];        }else{            throw new Error("未找到参数【" + globalVar.v.fieldNm_fQueryCancel + "】");        }        globalVar.f.sendMessage2Java = function(request){            // 即 window.csh_Query({...})            window[urlParamObj[globalVar.v.fieldNm_fQuery]]({                request: request,                onSuccess: function(response) {                    alert("onSuccess:" + response);                    globalVar.v.sendMessage2Java_response_onSuccess = response;                },                onFailure: function(error_code, error_message) {                    alert("error_code:" + error_code);                    alert("error_message:" + error_message);                    globalVar.v.sendMessage2Java_error_code = error_code;                    globalVar.v.sendMessage2Java_error_message = error_message;                }            });        }    </script></body></html>
CshJcefJsInjectHandlerDemo

client_ 中 addRequestHandler:

// 任意 script 执行之前被调用指定的jsclient_.addRequestHandler(new CshJcefJsInjectHandlerDemo());

核心代码

        if (frame.isMain()) {            LOGGER.info("注入JavaScript代码 frame.getURL()===:" + frame.getURL());            try {                // 让线程 sleep 一秒保证 executeJavaScript 方法能够执行                 Thread.sleep(1000);                Thread.sleep(100);// test 3 ok//                Thread.sleep(10);// test 不成,会注入失败            } catch (InterruptedException e) {                LOGGER.info("sleep失败", e);            }            // 注入JavaScript代码            // url(第二个参数):这个参数为代码提供了上下文,它通常用于开发者工具中,以显示代码来源。这个URL不会被用来下载脚本,它是一个虚拟的源参考,有助于调试。例如,如果在控制台中抛出了错误,这个URL就会被用来表示代码的来源。            // startLine(第三个参数):这个参数是一个整数,指定了代码在源文件中的起始行号。这对于调试也很有用,因为它可以帮助开发者确定代码中的错误位置。如果你没有具体的行号信息,通常使用0作为默认值。            //【】 尽管 executeJavaScript 在 onBeforeBrowse 中被调用,但它只能确保在此时刻执行,无法控制相对于页面中其他已有脚本的执行顺序。            frame.executeJavaScript("var injectDataJcef5 = injectDataJcef5 || '注入的数据';", frame.getURL(), 0);        }

完整代码:

package com.virhuiai.JBCefBrowser.handler;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.cef.browser.CefBrowser;import org.cef.browser.CefFrame;import org.cef.callback.CefAuthCallback;import org.cef.callback.CefCallback;import org.cef.handler.CefLoadHandler;import org.cef.handler.CefRequestHandler;import org.cef.handler.CefResourceRequestHandler;import org.cef.handler.CefResourceRequestHandlerAdapter;import org.cef.misc.BoolRef;import org.cef.network.CefRequest;import org.cef.network.CefResponse;// 实现了CefRequestHandler接口和CefResourceRequestHandler接口,// 用于处理浏览器的请求事件。public class CshJcefJsInjectHandlerDemo extends CefResourceRequestHandlerAdapter implements CefRequestHandler {    private static Log LOGGER = LogFactory.getLog(CshJcefJsInjectHandlerDemo.class);    // 在浏览器发起导航前调用,可以在此方法中拦截请求    // 当浏览器即将加载一个页面之前,这个方法被调用。    // bard :    // onBeforeBrowse方法可以用来实现以下功能:    //阻止浏览器加载某些页面。    //修改页面的 URL。    //在页面加载之前执行自定义代码。    //执行时机的问题: onBeforeBrowse 方法是在浏览器即将发起导航请求时调用的,    // 这意味着它是在任何页面内容(包括 JavaScript 文件和 HTML 内容)被加载之前执行的。    // 然而,这个方法中注入的 JavaScript 代码实际上是在页面开始加载时注入的,但并不能保证在所有其他 JavaScript 执行之前运行。    @Override    public boolean onBeforeBrowse(CefBrowser browser, CefFrame frame, CefRequest request,                                  boolean user_gesture, boolean is_redirect) {        //主框架是指浏览器中加载的页面的顶级框架,通常是整个页面的主要内容。        // 当浏览器加载页面时,会创建一个主框架,并在主框架中显示页面的内容。        //        //因此,frame.isMain()为假值的情况是当frame表示的是非主框架,例如内嵌在页面中的一个框架或iframe等。        if (frame.isMain()) {            LOGGER.info("注入JavaScript代码 frame.getURL()===:" + frame.getURL());            try {                // 让线程 sleep 一秒保证 executeJavaScript 方法能够执行                 Thread.sleep(1000);                Thread.sleep(100);// test 3 ok//                Thread.sleep(10);// test 不成,会注入失败            } catch (InterruptedException e) {                LOGGER.info("sleep失败", e);            }            // 注入JavaScript代码            // url(第二个参数):这个参数为代码提供了上下文,它通常用于开发者工具中,以显示代码来源。这个URL不会被用来下载脚本,它是一个虚拟的源参考,有助于调试。例如,如果在控制台中抛出了错误,这个URL就会被用来表示代码的来源。            // startLine(第三个参数):这个参数是一个整数,指定了代码在源文件中的起始行号。这对于调试也很有用,因为它可以帮助开发者确定代码中的错误位置。如果你没有具体的行号信息,通常使用0作为默认值。            //【】 尽管 executeJavaScript 在 onBeforeBrowse 中被调用,但它只能确保在此时刻执行,无法控制相对于页面中其他已有脚本的执行顺序。            frame.executeJavaScript("var injectDataJcef5 = injectDataJcef5 || '注入的数据';", frame.getURL(), 0);        }        // 返回false表示不拦截请求,继续加载页面。        return false;//        return true;    }    @Override    public boolean onResourceResponse(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response) {//        response.get        return false;    }    @Override    public boolean onBeforeResourceLoad(CefBrowser browser, CefFrame frame, CefRequest request) {        // 返回 false 以继续加载资源        return false;    }    @Override    public boolean onOpenURLFromTab(CefBrowser cefBrowser, CefFrame cefFrame, String s, boolean b) {        return false;    }    @Override    public CefResourceRequestHandler getResourceRequestHandler(CefBrowser cefBrowser, CefFrame cefFrame, CefRequest cefRequest, boolean b, boolean b1, String s, BoolRef boolRef) {        return null;    }    @Override    public boolean getAuthCredentials(CefBrowser cefBrowser, String s, boolean b, String s1, int i, String s2, String s3, CefAuthCallback cefAuthCallback) {        return false;    }    @Override    public boolean onCertificateError(CefBrowser cefBrowser, CefLoadHandler.ErrorCode errorCode, String s, CefCallback cefCallback) {        return false;    }    @Override    public void onRenderProcessTerminated(CefBrowser cefBrowser, TerminationStatus terminationStatus) {    }}

Jcef跨平台H5(HTML5)开发中,

标签: #js一个方法执行完执行另一个方法