2
头图

Improve the development experience with Chrome plug-ins

Event background

  • As part of the company's old projects (the number is quite large), the front-end is developed by hybrid and app. The login front-end is to splice a token in the URL when the 161a43b6fd17ac app is opened. When debugging the development environment, use Charles to capture the package and the page URL. Take it out (with token in url), so that you can simulate the user login status locally during development
  • Problem: Because the account service in the development environment is not very stable, and some test accounts that are frequently used are used by many people, this leads to a problem: token always fails frequently
  • In the past, when the token is invalid, you can log in again with the app or change your account, and then continue to use Charles to grab a new token. This process is not only a waste of time but also annoying

Solution

  • Thinking of developing a Chrome plug-in, enter the phone number and password in the plug-in, and then automatically token into the URL accessed by the development environment
  • The effect is as follows: click on the Chrome plug-in, enter the phone number and password, and click OK to put the obtained token into the current page url. If there is a token in the current url (ie expired token), replace it

How to develop a Chrome plug-in

Implementation of my Chrome plug-in mock_token

  • I mainly used browserAction 's display form as shown in the figure above.
  • Development steps:
  • manifest.json file is necessary, focusing on two configurations: content_script/browser_action

        "name": "Mock_Token",
        "version": "2.1",
        "description": "一个获取用户token的插件",
        "manifest_version": 2, // 此处必须是2
        // 直接注入当前页面的js
        "content_scripts": [
            {
                "matches": ["http://localhost/*"],
                // 直接注入页面
                "js": ["content.js"],
                "run_at": "document_start"
            }
        ],
        // 浏览器状态栏的展示
        "browser_action": {
            // 插件图标
            "default_icon": "32.png",
            // 插件标题
            "default_title": "获取token-Chrome插件",
            // 插件的展现页面即一个HTML文件
            "default_popup": "./popup.html"
        },
        // 插件所需要的权限
        "permissions": ["storage", "webRequest", "tabs", "http://*/*", "https://*/*"],
        // csp安全策略设置,否则在HTML外链引入jQuery的时候会报csp安全错误
        "content_security_policy": "script-src 'self' https://cdn.bootcdn.net; object-src 'self'"
  • popup.html Click the modal box that pops up in the browser status bar

    <!DOCTYPE html>
    <html lang="en">
    <!-- head省略 -->
    <head></head>
    <!-- 样式省略 -->
    <style></style>
    <body>
        <input id="phone" type="text" placeholder="请输入手机号" maxlength="11">
        <input id="pwd" type="text" placeholder="请输入密码" maxlength="6">
        <button id="btn">确定</button>
    </body>
    <!-- 引入外链js库必须要在manifest.json里面配置CSP安全策略 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <!-- 此文件不可写内联script标签,必须用引入方式 -->
    <script src="./popup.js"></script>
    </html>
  • popup.js is the interactive logic of the modal content

     const phone = document.querySelector("#phone");
     const pwd = document.querySelector("#pwd");
     const btn = document.querySelector("#btn");
    
     // 页面初始化的先从Chrome的storage里面读取上次填写的手机号密码
     chrome.storage.sync.get({ phone: "", pwd: "" }, function (items) {
         phone.value = items.phone;
         pwd.value = items.pwd;
     });
    
     btn.addEventListener("click", () => {
         getToken(phone.value, pwd.value);
         // 每次点击确定的时候将手机号密码写入存储
         chrome.storage.sync.set({ phone: phone.value, pwd: pwd.value }, function () {
             console.log("保存成功!");
         });
     });
    
     function getToken(phone_no, password) {
         let params = {
             phone_no: phone_no || "10012345632",
             password: password || "123456",
         };
         const url = "https://xxx.com/login?args=" + JSON.stringify(params);
    
         fetch(url).then((res) => res.json())
             .then((res) => {
                 sendMsg(res.token)
             });
     }
    
     // 通过postmessage的形式将信息传给content-script
     // 因为popup.html 不能操作当前宿主页面而content-script要将信息传递出去
     // 另外一点值得提的是当前文件可以无视跨域直接调接口而content-script受跨域限制
     function sendMsg(token) {
         chrome.tabs.query({ active: true, currentWindow: true}, 
         (tabs) => {
                 const message = { token };
                 chrome.tabs.sendMessage(tabs[0].id, message);
             }
         );
     }
  • content.js is directly injected into the host page content-script

    // onMessage 监听 popup.js传递过来的信息
    chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
        console.log("接收了来自 popup.js的消息", req.token);
        replaceToken(req.token);
    });
    
    // 直接替换当前url中的token
    function replaceToken(token) {
        const url = window.location.href;
        if (!url.includes("token")) {
            window.location.href += url.includes("?")
            ? `&token=${res.token}`
            : `?token=${res.token}`;
        } else {
            window.location.href = url.replace(/(token=)[^&]+/, "$1" + res.token);
        }
        // 单页面应用由于直接改变token页面不会刷新,所以需要手动reload一下
        setTimeout(() => window.location.reload();, 500);
    }

    About debugging

  • content.js can be debugged directly in the console of the current page
  • popup.js should be opened separately in a console, the operation is shown in the figure below
  • Summarize

  • The above is all the content of the plug-in development- is very simple 😂😂[旺柴]
  • Of course, the Chrome plug-in itself can still develop a lot of fun and useful things. For example, if the function to be implemented is very complex, you can introduce modern front-end development frameworks React/Vue

大桔子
588 声望51 粉丝

下一步该干什么呢...