Computer turns on child protection mode (3): browser plug-in writing

Time:2022-5-16

When he returned home after a year, his brother was still addicted to various cartoons for a long time. Considering that changing the host would ban the whole video website and unable to view some learning videos (he had to manually ban hhhhhh), he decided to write a browser plug-in to filter the content.

environment

Local development environment:

  • Windows 10
  • Chrome browser

Server environment:

  • Ubuntu 20.04
  • Python

requirement analysis

Because the password is required to install a new application last time, uninstall other browsers on the computer and only install Chrome browser, so that it can not bypass the plug-in we wrote (as for whether my brother will uninstall the plug-in, you can fake the plug-in to make him unaware of this problem).

Then, the functional requirements of the plug-in, mainly including the following points:

  1. Ban all kinds of mainstream cartoons
  2. Ban all kinds of web games
  3. Ban all kinds of emotional violence and other web content that is not conducive to children’s physical and mental health
  4. Keep all kinds of popular science and learning related web pages

Programming

According to the above demand analysis, you can write a browser plug-in to verify the web page title, such asBear hauntPleasant SheepAnd other keywords, then jump to other pages.

Considering that only through the front-end verification, when the keyword is updated, the plug-in needs to be repackaged and installed, which can not realize the rapid iteration and update of the program. Therefore, consider adding a background program. The front-end sends the obtained web page title to the background, which will be verified by the background and return to the Boolean value. After the front-end receives the Boolean value, it will be banned or released.

Programming

Browser plug-in framework

First, build a browser plug-in framework.

Create a new folder named after the plug-inDDblocker, then find an icon and create a new one namedmanifest.jsonFile:

{
  "manifest_version": 2,
  "name": "DDBlocker",
  "version": "1.0",

  "description": "Filter the video list before play it.",

  "icons": {
    "48": "icons/border-48.png"
  },

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["ddblocker.js"]
    }
  ]
}

Among them,nameIs the name of the plug-in, which can be named at will,descriptionFor program description,iconsFill in the previous icon path(48The length and width of the icon is 48 * 48 pixels, which is best provided here at the same time48and96Pixel long and wide icon),content_scriptsMediummatchesIndicates where to enable the plug-in, hereall_urlsIndicates that all URLs are enabled, andjsIt is the entry of the JS function of the plug-in, that is, the main content of the plug-in. The subsequent programming is in this JS file.

Create a new file. The file name is the name defined in the above configuration file. Here isddblocker.js, open the file and you can start writing function functions.

Final document directory:

Computer turns on child protection mode (3): browser plug-in writing

directory structure

Plug in function

The plug-in is mainly divided into two functions: obtaining the page title and requesting the server and performing corresponding operations according to the return value of the server.

First, write a function that performs the corresponding operation according to the return value of the server:

function dd_callback(response_value){
    if (response_value == true){
        // contine as default.
        return true;
    }else{
        console.log(response_value);
        location.href = 'about:blank';
    }
}

When the return value istrueRelease without any operation; When the return value isfalseJump to a blank page when.

Then insert this function into the page:

function adding_elements(){
    // dd function
    var a = document.createElement("script");
    a.type = 'text/javascript';
    a.innerHTML = dd_callback.toString();
    document.body.appendChild(a);
}
adding_elements();

The above functions are passed heretoString()Convert to a string and build ascriptTag, insert into the page.

Then, you need to write a function that requests the server. Considering the cross domain problem of the browser, the method of jsonp is adopted here:

function jsonp_request(){
    // request script
    var b = document.createElement('script');
    title = document.title;
    b.src = build_url('dd_callback', title);
    document.body.appendChild(b);
}

adoptdocument.titleGet the label page title by insertingscriptLabel and specify its SRC as the address of the remote server (use the function here)build_url()To build a URL) and send a cross domain request. The function of building a URL is as follows:

function build_url(callback_f, title){
    url = 'http://ddblocker.xxx.com:5000/ddblocker?title=' + title;
    
    // adding callback function.
    url += '&callback=' + callback_f;
    return url;
}

Here, the remote server is turned on5000Port, interface isddblocker, receivetitleandcallbackTwo parameters, where,titleUsed by the server to determine whether the website should be released, andcallbackUsed to return to the front end to execute the callback function.

Server programming

Since all judgment operations are performed on the server side, it is necessary to write server-side code. Here, flash is used as the web service of back-end code.

First, create a flash application and define the interface:

from flask import Flask, request
app = Flask('ddblocker')

@app.route('/ddblocker')
def hello_dd():
    pass

if __name__ == "__main__":
    app.run(
        host='0.0.0.0',
        port=5000,
        # debug=True
    )

Then write the function content:

def hello_dd():
    # server logic here.
    # request -> data, document.title from client area.
    # server should allow jsonp protocol and return javascript which call the target function with args 'true' or 'false'.
    title = request.args.get('title')
    print(title)
    callback_f = request.args.get('callback')
    
    if not title or not callback_f:
        return 'location.href="about:blank"'
    
    return build_function_to_javascript( callback_f, title )

First, receive the passed parameters, and then determine whether they are empty. If any parameter is empty, return the JS code that jumps to the blank page, otherwise return to executiondd_callbackJS code of the function (the code passes through the function)build_function_to_javascriptConstruction).

The function to build the returned JS code is as follows:

def build_function_to_javascript(function_name, function_args):
    args_to_string = '(' + check_function(function_args) + ')'
    js_code = function_name + args_to_string
    return js_code

Among them, the shape such asdd_callback(true)JS code, the parameters in the code use the functioncheck_functionTo determine whether to release.

The code to judge whether the title of the label page meets the requirements is as follows:

import pickle

# init
# read pickle file save the lists.
try:
    with open('./banned_list.pkl','rb') as f:
        banned_list = pickle.load(f)
except:
    banned_list = set() # empty


def check_function(title):
    for t in banned_list:
        if t in title:
            return 'false'
    return 'true'

Here, a file is used to store prohibited terms, which can be judged by blacklist. Read the file, traverse each term in the file, and determine whether the title contains the keyword. If yes, returnfalse, otherwise returntrue

To facilitate adding entries, set an interface for adding entries:

@app.route('/Blocker_changer')
def manager():
    operation_t = request.args.get('type')
    title = request.args.get('title')
    
    if not operation_t or not title:
        # format not supported.
        # return empty.
        return 'Error operations'
    else:
        # check operations and do something here.
        if operation_t == 'add':
            banned_list.add(title)
            return 'adding success'
        elif operation_t == 'remove':
            try:
                banned_list.remove(title)
            except:
                # pass
                return 'title does not exists'
            return 'remove success'
        else:
            return 'error oprations'

This interface receivestitleandtypeAs a parameter, it represents the global variable of the disabled word and the corresponding operation (adding or deleting an entry) to store it in the previously read file content.

When the program is interrupted, the content of the current file needs to be saved, so it is necessary to capture various abnormal signals of program interruption. Therefore, the operation function of program interruption is added:

def signal_handler( sig, frame):
    print(sig)
    with open('./banned_list.pkl','wb') as f:
        pickle.dump(banned_list, f)
    raise KeyboardInterrupt

Then add the signal capture statement to the main function:

if __name__ == "__main__":
    signal.signal( signal.SIGINT, signal_handler )
    signal.signal( signal.SIGTERM, signal_handler )
    signal.signal( signal.SIGSEGV, signal_handler )
    
    app.run(
        host='0.0.0.0',
        port=5000
    )

Plug in operation

Open Chrome browser, click the button in the upper right corner and selectMore tools->Extender

Computer turns on child protection mode (3): browser plug-in writing

Extender

Then click the button in the upper right corner to open the developer mode, and click the button on the leftLoad the decompressed extension, select the project folder we created:

Computer turns on child protection mode (3): browser plug-in writing

image.png

Then you can see that the plug-in is loaded successfully. Click the button in the lower right corner to enable the plug-in:

Computer turns on child protection mode (3): browser plug-in writing

Plug in loaded successfully

Then open a page at will. Take Baidu as an example. Right click on the page and selectinspect, check the console and find that the plug-in reports an error:

Computer turns on child protection mode (3): browser plug-in writing

HTTPS reminder

Error reporting promptddblocker.js:32 Mixed Content: The page at 'https://www.baidu.com/' was loaded over HTTPS, but requested an insecure script 'http://ddblocker.xxxxx.com:5000/ddblocker?title=%E7%99%BE%E5%BA%A6%E4%B8%80%E4%B8%8B%EF%BC%8C%E4%BD%A0%E5%B0%B1%E7%9F%A5%E9%81%93&callback=dd_callback'. This request has been blocked; the content must be served over HTTPS.Because the baidu page is HTTPS and the address requested by the plug-in is HTTP, the request is locked and HTTPS must be used. Therefore, the server needs to be configured with HTTPS and an SSL certificate.

A domain name is required to apply for a certificate. I use Alibaba cloud domain name service, so open Alibaba cloud console and searchSSL certificate, click on the left after the search is completedSSL certificate, and then clickFree certificate, clickBuy now

Computer turns on child protection mode (3): browser plug-in writing

Alibaba cloud SSL certificate application

In the purchase interface, check the following options in turn (you can’t apply repeatedly here because you have already purchased):

Computer turns on child protection mode (3): browser plug-in writing

Purchase SSL certificate

After clicking purchase, because the amount is 0, it will directly jump to the success interface. Then select certificate application in the previous interface, fill in your own domain name (fill in a subdomain name here) and information, and then click Next:

Computer turns on child protection mode (3): browser plug-in writing

Apply for domain name certificate

Then add an analysis record according to the content shown in the figure, and clickverificationButton, click after passingSubmit for review

Computer turns on child protection mode (3): browser plug-in writing

Operation guidance

Then you will see an additional Certificate in the previous list. Click the download button:

Computer turns on child protection mode (3): browser plug-in writing

Certificate application succeeded

choiceotherDownload:

Computer turns on child protection mode (3): browser plug-in writing

Download certificate

After decompression, you will see two suffixes, namelypemandkeyFile:

Computer turns on child protection mode (3): browser plug-in writing

Downloaded certificate

Put it in the same folder as the script of the server, and change the main function of the script to:

if __name__ == "__main__":
    app.run(
        host='0.0.0.0',
        port=5000,
        ssl_context=('./7219406_ddblocker.xxx.com.pem','7219406_ddblocker.xxx.com.key')
    )

Change the request header of the URL requested by the plug-in script at the front end tohttps

Run the script using the command:

python ddblocker.py

Open a new tab and access the linkhttps://ddblocker.xxx.com:5000/Blocker_changer?type=add&title= Bear haunt, displayadding success

Computer turns on child protection mode (3): browser plug-in writing

Add entry

Then re import the plug-in of the front end. Open a new tab, visit Baidu and find that the display is normal. Then open station B, search for the presence of bears, click a video at will, and find that the page jumps to a blank page. The plug-in is successful:

Computer turns on child protection mode (3): browser plug-in writing

The plug-in is successfully implemented

Subsequent iterations and Prospects

  • The plug-in can be disguised, for example, it will not be displayed on the right side of the browser bookmark bar, and its name and icon will be changed to something that is not easy to be noticed
  • Another field can be added in the front end to transmit the website it browses to the server. The server stores the title and website of each request received, so as to monitor the browsing content of the younger brother
  • It can be used as a front-end visual interface to add and delete entries, which is more convenient
  • Authenticate the server to prevent the reverse operation from deleting all fields hhhh

reference material

Recommended Today

Business scenario actual combat (I) evolution of meituan home commodity inventory

catalogue General catalogue of series Architecture evolution Anti oversold Unitization Platformization Anti oversold MySQL synchronization to prevent oversold Redis synchronization to prevent oversold uniformity MySQL synchronization to achieve consistency against oversold Redis synchronization realizes the consistency of anti oversold Reference articles General catalogue of series Actual business scenario summary Architecture evolution Architecture evolution diagram png […]