Improving the development experience with Chrome plug-ins

Improving the development experience with Chrome plug-ins

Event background

  • Because some of the company's old projects (quite a large number) are developed by hybird and app, the login status of the front end is to splice a token at the url when the app is opened (there are security risks due to historical problems). When debugging the development environment, use charles to grab the package and take out the page url (the url contains a token), so that the login status of users can be simulated locally during development
  • Problem: because the development environment account service is not very stable, and many people use some test accounts that are often used, this leads to a problem: token s always fail frequently
  • In the past, when the token failed, you would log in again with the app or change your account, and then continue to use charles to find a new token. This process is not only a waste of time, but also very annoying

resolvent

  • Think of developing a Chrome plug-in, enter the mobile phone number and password in the plug-in, and then automatically spell the obtained token into the url accessed by the development environment
  • The effect is as follows: click the Chrome plug-in, enter the mobile phone number and password, and click OK to spell the obtained token into the current page url. If a token (i.e. expired token) already exists in the current url, replace it

How to develop a Chrome plug-in

My Chrome plugin mock_ Implementation of token

  • I mainly use the presentation form of broweraction here, as shown in the figure above
  • Development steps:
  • A mandatory manifest.json file focuses on two configurations: content_script/browser_action

        "name": "Mock_Token",
        "version": "2.1",
        "description": "A get user token Plug in for",
        "manifest_version": 2, // This must be 2
        // Directly inject js into the current page
        "content_scripts": [
            {
                "matches": ["http://localhost/*"],
                // Direct injection page
                "js": ["content.js"],
                "run_at": "document_start"
            }
        ],
        // Display of browser status bar
        "browser_action": {
            // Plug in Icon
            "default_icon": "32.png",
            // Plug in title
            "default_title": "Get token chrome plug-in ",
            // The presentation page of the plug-in is an HTML file
            "default_popup": "./popup.html"
        },
        // Permissions required by the plug-in
        "permissions": ["storage", "webRequest", "tabs", "http://*/*", "https://*/*"],
        // csp security policy settings, otherwise csp security errors will be reported when jQuery is introduced into the HTML external chain
        "content_security_policy": "script-src 'self' https://cdn.bootcdn.net; object-src 'self'"
  • Pop.html is the modal box that pops up by clicking the browser status bar

    <!DOCTYPE html>
    <html lang="en">
    <!-- head ellipsis -->
    <head></head>
    <!-- Style ellipsis -->
    <style></style>
    <body>
        <input id="phone" type="text" placeholder="Please enter your mobile phone number" maxlength="11">
        <input id="pwd" type="text" placeholder="Please input a password" maxlength="6">
        <button id="btn">determine</button>
    </body>
    <!-- Introduction of external chain js Library must be in manifest.json Inside configuration CSP security policy  -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <!-- This file is not writable inline script Labels must be imported -->
    <script src="./popup.js"></script>
    </html>
  • Pop.js is the interactive logic of the content of the modal box

     const phone = document.querySelector("#phone");
     const pwd = document.querySelector("#pwd");
     const btn = document.querySelector("#btn");
    
     // For page initialization, first read the last filled mobile phone number and password from 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);
         // Write the mobile phone number and password into the storage every time you click OK
         chrome.storage.sync.set({ phone: phone.value, pwd: pwd.value }, function () {
             console.log("Saved successfully!");
         });
     });
    
     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)
             });
     }
    
     // Pass the information to content script in the form of postmessage
     // Because pop.html cannot operate the current host page, content script needs to pass the information out
     // Another point worth mentioning is that the current file can ignore the cross domain direct call interface, and content script is limited by cross domain
     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 main page by content script

    // onMessage listens for the information passed by popup.js
    chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
        console.log("Received from popup.js News of", req.token);
        replaceToken(req.token);
    });
    
    // Directly replace the token in the current url
    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);
        }
        // For single page applications, the token page will not be refreshed if it is changed directly, so it needs to be reload ed manually
        setTimeout(() => window.location.reload();, 500);
    }

    summary

  • That's all about the plug-in development - very simple 😂😂 [Wang Chai]
  • Of course, the Chrome plug-in itself can develop many interesting and useful things. For example, if the functions to be implemented are very complex, modern front-end development frameworks such as React/Vue can be introduced

Posted on Sun, 28 Nov 2021 07:51:53 -0500 by Sneef