primers

Then Chrome extension: get started, and then start to realize their own idea at the beginning: network request filtering. Simply put, it is to listen to all the requests of a website and show the requests you want in the extension. The extension name is Capture Request.

Specification of requirements

The above idea is a little vague. To achieve this, combined with the examples in the documentation, the following are done:

  1. Extensions should have corresponding ICONS and prompts.
  2. Click the toolbar extension icon to open a new Tab page that displays information about the request.
  3. The extension listens for web site requests in active tabs and can be configured to filter the listening URL.
  4. Supports filtering and exporting of listened requests based on URL.

Some features are not easy to find directly in the documentation, in this case, it is recommended to find an open source extension in the Chrome store, according to the effect of the use of some oF the API, and then find the corresponding documentation. Some implementations of FeHelper are referenced here. Note that FeHelper is developed based on Manifest_version 2. The following development extension is based on The recommended version 3. For the complete code, see Capture Request.

implementation

Icon configuration

As described in getting started, ICONS can appear in toolbars, extension management pages, permissions warnings, and favicons, configured in manifest.json in the following related fields:

{
  "name": "Capture Request"."description": "Capture Request"."version": "1.0"."manifest_version": 3."action": {
    "default_icon": {
      "16": "xxx.png"."32": "xxx.png",}},"icons": {"16": "xxx.png"."32": "xxx.png",}}Copy the code

A detailed description of what size ICONS should be used where is provided here. PNG images are recommended for documentation. Following this, you can find ICONS that are too small to look obvious, or you can use a larger size, Chrome will compress the image to the desired size.

Click on the extension to open the new Tab page

Clicking on the extension in the entry window opens a popover. Popup, Tooltip, Omnibox, Context Menu, and Override Pages are described in the document Design the User Interface. Override Pages is the most likely option, but it didn’t work when I tried it, so I looked at someone else’s implementation and found that I could open a new Tab by listening for icon clicking events.

But what looks like a straightforward API actually has a few more things to consider:

  1. Where is this event monitored?
  2. When do you listen for this event?
  3. How do I open a new Tab?
  4. Are permissions required, and if so, what permissions are involved?

Adding functionality to the starter is done through background scripting, which I find very important at the beginning of the document:

Extensions are designed to change or enhance the Chrome browsing experience through event-based programming.

As you can see from the documentation, the first and second issues mentioned above can be addressed in background scripts with the required permissions for scripting.

The API used to open a Tab is Chrome. tabs, and the permissions required are tabs.

The main way to do this is to add the following configuration to manifest.json:

{...+ "permissions": [
+ "scripting",
+ "tabs",
+],
+ "background": {
+ "service_worker": "background.js"
+},. }Copy the code

Then create a background script file called background.js and add the following logic code:

chrome.action.onClicked.addListener(() = > {
  chrome.tabs.create({
    url: 'page.html'
  });
});
Copy the code

Listen for requests and configurations

The main points to consider in order to display a request on the active Tab web site to an open extension page are:

  1. How do I find active Tabs?
  2. How do I intercept web requests?
  3. How are intercepted requests synchronized to extended custom pages?

With tabs open, you can see that the related API is also in Chrome. Tabs, and you can see that the query method is provided to solve the first problem.

The method of interception request is searched on the Internet and found the document Chrome. webRequest, which introduces the life cycle and triggered events of the request in the extension in detail. After comparison and consideration, I finally decide to listen to the onResponseStarted event, and the permission required is webRequest. That solves the second problem.

Similarly, you can cache the request to Chrome. storage and then retrieve it from the extension page. The required permission is storage. For data synchronization, you can listen for the chrome.storage.onChanged event to get the latest data changes. This solves problem number three.

During debugging, an error message is displayed when the chrome.storage.sync request reaches a certain amount. This method is not suitable for scenarios where a large amount of requested data is stored. Chrome. Storage.

The configuration of the filter request can be handled directly as in the introduction configuration, but it is important to note that whenever the configuration is updated, the onResponseStarted event needs to be listened again.

The main approach is to add webRequest and storage to the manifest.json permissions field.

Add the main code to background-js:

// Store request data defaults
let requestList = []
// Default value for url filtering
let urlPattern = '<all_urls>'

// The handler that listens for the request event
const handlerResponseStarted = (details) = > {
  // Find the active Tab
  chrome.tabs.query({ active: true }, (tab) = > {
    requestList.unshift(details)
    chrome.storage.local.set({ requestList });
    return { cancel: true}; })}// Listen for storage change events
chrome.storage.onChanged.addListener((changeObj, areaName) = > {
  const { urlPattern } = changeObj
  // urlPattern is changed in page.html
  if(areaName ! = ='local'| |! urlPattern) {console.warn('urlPattern does not change')
    return;
  }
  const { newValue } = urlPattern
  const hasAddListen = chrome.webRequest.onResponseStarted.hasListener(handlerResponseStarted)
  if (hasAddListen) {
    chrome.webRequest.onResponseStarted.removeListener(handlerResponseStarted);
  }
  chrome.webRequest.onResponseStarted.addListener(
    handlerResponseStarted,
    { urls: [newValue] },
  );
})
Copy the code

Add the script file pages.js for the extended page page.html and add the key logic:

  chrome.storage.onChanged.addListener((changeObj, areaName) = > {
    const { requestList } = changeObj
    // Check if the requestList has changed since background.js is also monitored
    if(areaName ! = ='local'| |! requestList) {console.warn('requestList does not change')
      return;
    }
    const { newValue } = requestList || { newValue: []}const newItem = newValue[0] | |null
    if(! newItem) {console.warn('no data')
      return;
    }
    // Display the logic of the data
    showData(newItem)
  })
Copy the code

Export data

I have captured the data I want and need to export it to local scenarios. I refer to the implementation in FeHelper to find the document Chrome.downloads and the required permission is downloads.

The main approach is to add downloads in the Manifest.json permissions field.

Add key logic to pages.js:

  let localFilterList = []; // Page filtered data
  // Click the export button
  const exportEle = document.querySelector('#operate-export')
  exportEle.addEventListener('click'.() = > {
    if(! localFilterList.length) { alert('No valid data')
      return;
    }
    const txt = JSON.stringify(localFilterList)
    let blob = new Blob([txt], { type: 'application/octet-stream' });
    // The file name gets the time in seconds, which can be defined as you like
    let dt = (new Date()).getSeconds();
    chrome.downloads.download({
      url: URL.createObjectURL(blob),
      saveAs: true.conflictAction: 'overwrite'.filename: dt + '.json'
    });
  })
Copy the code

The resources

wastebasket

Recently I watched the TV series “Fortress Besieged”. Although it was very early, it was really interesting. It was said that it was filmed completely according to the original work, without any adaptation.

I don’t know when it starts, but I always thought the whole book was about a marriage siege.