1. 程式人生 > >黃聰:如何擴充套件Chrome DevTools來獲取頁面請求

黃聰:如何擴充套件Chrome DevTools來獲取頁面請求

1. Chrome DevTools Extension

剛看到的時候,我也覺得很神奇,
因為React Developer Tools和其他Chrome Extension不同,
它居然出現在了Chrome開發者工具欄中,和原生的DevTools一樣強大。
例如,可以審查元素,檢視元素的屬性,等等。

比起普通的Chrome Extension,Chrome DevTools Extension可以訪問更多API,例如,
(1)devtools.inspectedWindow
(2)devtools.network
(3)

devtools.panels
其中包括了,與當前審查視窗相關的,與網路請求相關的,以及與開發者工具欄相關的API。

2. 背景 & 基本概念

在某一具體專案中,有一個這樣的需求,
我們需要選擇頁面中發起的http請求,然後將它們儲存到資料庫中。

由於頁面發起的請求可能會發往不同的伺服器,所以在伺服器端解決這個問題就顯得比較麻煩,
而編寫一個Chrome DevTools Extension會更簡單直接。

下文我將這個功能的核心抽離出來,作為一個例子,來還原Chrome DevTools Extension的編寫方法。
為此,我們先熟悉幾個基本的概念。

(1)tab頁

Chrome瀏覽器是由tab頁組成的,一個瀏覽器例項中可以開啟多個tab頁。


(2)DevTools Window

每個tab頁,都可以開啟自己的開發者工具視窗,稱為DevTools Window。


注意,每個tab頁都有自己獨立的DevTools Window,
只是切換tab頁的時候,只會顯示當前tab頁的DevTools Window。

(3)DevTools Page 和 Panel

下面我們來建立一個Chrome DevTools Extension專案,目錄結構如下,

chrome-devtools-extension-example
├── devtools.html    // DevTool Page
├── devtools.js      // DevTool Page中引用的js
├── manifest.json    // 入口
├── panel.html       // 開發者工具欄選項卡頁面
└── panel.js         // 選項卡頁面中引用的js

其中manifest.json是入口,它會宣告一個對使用者不可見的DevTools Page。
在本例中為devtools.html

{
  "name": "PageRecorder",
  "version": "1.1.0",
  "minimum_chrome_version": "10.0",
  "description": "Record all http requests in a page.",
  "devtools_page": "devtools.html",
  "manifest_version": 2
}

DevTools Page對使用者是不可見的,如果需要在開發者工具欄中建立新的DevTool選項卡,
還需要在DevTools Page使用一下方法來建立,DevTool選項卡,官方稱為Panel。
原生的Panel包括,Elements,Console,Network,等等。

// 建立一個Panel
chrome.devtools.panels.create(

  // title
  'ChromeDevToolsExtensionExample',

  // iconPath
  null,

  // pagePath
  'panel.html'
);

以上,我們在DevTool Page中建立了一個新的Panel,名字為ChromeDevToolsExtensionExample

其中,panel.html,我們只是簡單的寫了一個Hello World!
值得注意的是,每個Panel都可以載入自己的html,js和css,且具有和DevTools Page一樣的許可權。

(4)Panel的生命週期

Panel只有在第一次被啟用的時候,才進行例項化,
同一個DevTools Window中的不同Panel切換時,不會重新載入。
當前tab頁重新整理時,Panel也不會重新載入。

DevTools Window關閉後,Panel將被銷燬。

因此,我們要想使用Chrome DevTools Extension,就必須先開啟開發者工具視窗,
然後再啟用我們新建的DevTools Panel。

3. 監聽請求

上文我們提到了,Chrome DevTools Extension可以訪問devtools.network API,
現在我們來展示使用chrome.devtools.network.onRequestFinished.addListener來獲取請求。
為此,我們新建了一個panel.js檔案,並在panel.html中引用它。

// Chrome DevTools Extension中不能使用console.log
const log = (...args) => chrome.devtools.inspectedWindow.eval(`
    console.log(...${JSON.stringify(args)});
`);

// 註冊回撥,每一個http請求響應後,都觸發該回調
chrome.devtools.network.onRequestFinished.addListener(async (...args) => {
    try {
        const [{
            // 請求的型別,查詢引數,以及url
            request: { method, queryString, url },

            // 該方法可用於獲取響應體
            getContent,
        }] = args;

        log(method, queryString, url);

        // 將callback轉為await promise
        // warn: content在getContent回撥函式中,而不是getContent的返回值
        const content = await new Promise((res, rej) => getContent(res));
        log(content);
    } catch (err) {
        log(err.stack || err.toString());
    }
});

以上就是panel.js的完整內容了,我們還需要做以下幾點說明,

(1)Chrome DevTools Extension中,不能直接使用console.log
所以本例中使用了devtools.inspectedWindow API中的chrome.devtools.inspectedWindow.eval方法,
在當前審查的視窗中直接求值一段js程式碼,從而間接實現列印日誌的功能。

(2)與獲取http請求的methodqueryStringurl不同的是,
我們需要呼叫getContent方法來獲取http響應體,
並且,getContent是一個高階的非同步函式

所謂高階函式,指的是,它接受一個回撥函式作為引數getContent(content=>{ })
這個回撥函式的引數content,才是對應http請求的響應體。

所謂非同步,指的是,當回撥函式還沒觸發的時候,getContent就已經返回了。
這也導致了事件監聽函式,也不得不具有非同步性。

(3)由於事件監聽函式是非同步的,
所以,有可能在上一個onRequestFinished事件還未處理完的情況下,
下一個onRequestFinished的監聽函式就又被觸發了。

這就導致了,以上例子中,log(method, queryString, url);log(content);
可能是亂序列印的。

總結

到此為止,我們最簡版的Chrome DevTools Extension示例已經介紹完了,
以下是可以執行的原始碼地址:github: chrome-extension-example
(注:不是master分支,而是simply分支。

Chrome擴充套件遵循一種優秀的設計原則,
那就是在設計系統的時候,應該想辦法讓擴充套件對使用者而言,與原生功能平權
這種對稱性,會拉近原生與擴充套件之間的距離,從而讓系統架構從一開始就建立在靈活的基礎之上。

相關推薦

如何擴充套件Chrome DevTools獲取頁面請求

1. Chrome DevTools Extension 剛看到的時候,我也覺得很神奇, 因為React Developer Tools和其他Chrome Extension不同, 它居然出現在了Chrome開發者工具欄中,和原生的DevTools

C#獲取網頁HTML內容的三種方式

HttpWebRequest httpReq; HttpWebResponse httpResp; string strBuff = ""; char[] cbuffer = new char[256]; int byteRead = 0; string filename

ffmpeg基本用法(轉)

sca wid cal ner aspect mp4 動態文本 tegra 控制輸出 FFmpeg FFmpeg 基本用法 本課要解決的問題 1.FFmpeg的轉碼流程是什麽? 2.常見的視頻格式包含哪些內容嗎? 3.如何把這些內容從視頻文件中抽取出來? 4.如

FFmpeg 使用指南

留下 時間 下一個 pseudo rdquo tle 全局 什麽 實時 1. ffmpeg 是什麽? ffmpeg(命令行工具) 是一個快速的音視頻轉換工具。 2. ffmpeg 的使用方式 命令行: ffmpeg [全局選項] {[輸入文件選項] -i &lsquo

FFmpeg視頻轉碼技巧之-crf參數(H.264篇)

文件中 one log 它的 忽略 enter center tail vcd 昨天,有個朋友給我出了個難題:他手上有一個視頻,1080P的,49秒,200多兆;要求在確保質量的情況下把文件壓縮到10M以內。 這是什麽概念呢?按照文件大小10M來計算,碼率是:10 x 8

濃縮的才是精華淺析GIF格式圖片的存儲和壓縮(轉)

meid 單獨 圖片分辨率 change 之前 dex 本質 0.11 blog http://www.cnblogs.com/qcloud1001/p/6647080.html 成文迪, 在Web前端摸爬滾打的碼農一枚,對技術充滿熱情的菜鳥,致力為手Q的建設添磚加瓦

PHP數據庫連接失敗--could not find driver 解決辦法

才會 pdo_mysq php 驅動 mysq sql ould 數據庫 對象 數據庫連接失敗could not find driver在調試一個PHP程序時,報了這個錯誤, could not find driver 經過一番查找,結合自己的思考和實踐,終於找到了問題所在

JQUERY判斷操作CHECKBOX選中、取消選中、反選、第二次無法選中的問題

clas 再次 box als 修改 api disable jquer checkbox 用JQuery做CheckBox全選和反選的時候,遇到一個問題。當用JQ控制全選,全取消一次以後,再次點擊全選,發現代碼變了,但是CheckBox沒有處於選中狀態。 $(

Jquery+DataTables插件,如何在ajax調用服務器數據後,自動給tr添加id屬性

jquer ida ted fnr pos sid idt 事件 all http://legacy.datatables.net/usage/callbacks#fnRowCallback 主要通過 fnCreatedRow 事件來實現 var table = $

jquery.bootgrid表格插件有的屬性(visibleInSelection、cssClass、headerCssClass、headerAlign)不能識別的解決辦法

oot div 添加 bsp load scl 不能 大小 jquer 主要是屬性大小寫問題,修改jquery.bootgrid.js文件,在function loadColumns()方法裏面添加下面的語句就好了 data.headerAlign = data.he

iOS $299刀企業證書申請的過程以及細節補充

別人 華夏鄧白氏 details 等等 .com 註意 內容 QQ blog 最近申請了iOS的 299刀企業證書,相關過程有些問題,分享出來,以便後來人參考。申請的過程我主要參考了別人以前的文章,鏈接如下:1、https://developer.apple.com/cn/

AngularJS最理想開發工具WebStorm

java tool row scl ng-repeat data- oom repos href Aug 29, 2013 Tags: angularangular.jsangularjswebstorm Comments: 23 Comments

通過 itms:services://? 在線安裝ipa ,跨過appstore

ins with 安裝 .get 解決方法 str war item 點擊 1.需要一個html文件,引導下載用戶在線安裝ipa <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">&

JS數學計算精度修正

function 浮點數 turn 計算 filesize add follow fun his 問題描述 如果我問你,4330.61乘以100等於多少,我猜你肯定跟我說:“肯定是 433061”啊! 是啊,要我我也是這麽回答,來來來我們

OTP動態密碼_Java代碼實現

-c name 好的 動態口令 comm final 並不是 bsp down OTP認知 動態口令(OTP,One-Time Password)又稱一次性密碼,是使用密碼技術實現的在客戶端和服務器之間通過共享秘密的一種認證技術,是一種強認證技術,是增強目前靜態口令

史上最詳細的kali安裝教程沒有之一

ner 沒有 操作系統 你是 著作權 如圖所示 鏈接 class 區域 首先在vm裏面新建虛擬機,直接選擇典型,然後下一步。 1 2 然後到了這一步,選擇中間的安裝程序光盤鏡像文件,然後去文件裏面

springboot配置通過工具類獲取spring容器中的bean

**由於公司電腦限制,完全手敲,有單字錯誤望理解** @component @SuppressWarnings("static-access") public class AppContext implements ApplicationContextAware{   &n

mysql主從配置(清晰的思路)

   mysql主從配置。鄙人是在如下環境測試的:   主資料庫所在的作業系統:win7   主資料庫的版本:5.0   主資料庫的ip地址:192.168.1.111   從資料庫所在的作業系統:linux   從資料的版本:5.0   從資料庫的ip地址:192.168.1.112 介紹完

Mysql主從配置,實現讀寫分離

大型網站為了軟解大量的併發訪問,除了在網站實現分散式負載均衡,遠遠不夠。到了資料業務層、資料訪問層,如果還是傳統的資料結構,或者只是單單靠一臺伺服器扛,如此多的資料庫連線操作,資料庫必然會崩潰,資料丟失的話,後果更是 不堪設想。這時候,我們會考慮如何減少資料庫的聯接,一方面採用優秀的程式碼框架,進行程式碼的優

浮動視窗程式碼(帶關閉按鈕+全屏漂浮)

<html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title>帶關閉按鈕的浮動視窗程式碼(全屏漂浮)</title></head