入門看看?Chrome外掛初窺與實踐

餓了麼新餐飲前端團隊發表於2020-02-29

Chrome外掛初窺與實踐

某頁面獲取資訊時,需要驗證token判斷登陸資訊。因為某些原因,在測試過程中,測試人員需要採用手動注入token的方式完成登陸,嚴重影響工作效率。

為了避免影響原始專案,所以採用chrome外掛的方式,製作一個簡單的登陸頁面模擬實際登陸情況,並向原頁面插入token用作登陸資訊。

本文記錄了chrome外掛開發的簡單概念與外掛開發過程,方便以後深入學習chrome外掛的開發。

1、核心概念

(1)manifest.json

每一個chrome外掛都必須有一個JSON格式的清單檔案放在根目錄。下面是一些常見的配置項,其中manifest_versionnameversion為三個必填項。

{
    // 必須
    "manifest_version": 2, // 清單檔案的版本,必須為2
    "name": "外掛名稱",
    "version": "1.0.0",
    
    // 推薦
    "default_locale": "en",
  	"description": "外掛描述",
  	"icons": {...}, // 圖示
    
    // 可選
    "background":{
        "page": "background.html" // 指定後臺頁面
        "scripts": ["js/background.js"] // 指定後臺指令碼
        "persistent": false // 推薦設定後臺指令碼為非持久
    },
      
    "browser_action": {	// 工具欄圖示(或page_action)
        "default_icon": "icon.png",
        "default_title": "圖示標題",// 圖示懸停時的標題,可選
        "default_popup": "popup.html"
    },
      
    "content_scripts": // 插入網頁的指令碼
    [
        {
            "matches": ["http://*/*", "https://*/*"], // 匹配頁面url,<all_urls> 表示匹配所有地址
            "js": ["content.js"], // 多個JS按順序注入
            "css": ["css/custom.css"],
            "run_at": "document_start"// 程式碼注入的時間,可選值: "document_start", "document_end", "document_idle",最後一個表示頁面空閒時,預設document_idle
        },
        {...}, // 可以配置多個規則
    ],
    "permissions": // 許可權申請
    [
        "contextMenus", // 右鍵選單
        "tabs", // 標籤
        "notifications", // 通知
        "webRequest", // web請求
        "storage", // 外掛本地儲存
    ],
    "default_locale": "zh_CN", // 預設語言
    "devtools_page": "devtools.html"// devtools頁面入口,注意只能指向一個HTML檔案,不能是JS檔案
}
複製程式碼

(2)content_script

通過content_script,我們可以向指定頁面注入JS或CSS。它與插入的頁面共享dom,即指令碼中使用的window物件與頁面中的window物件一致。

content_script可以使用如下幾種chrome APIs

  • i18n
  • storage
  • runtime(connect, getManifest, getURL, id, onConnect, onMessage, sendMessage)

(3)background

background是一個執行與瀏覽器的後臺指令碼/頁面,與當前瀏覽頁面無關。在配置中,可以通過page引入頁面,或通過scripts引入JS檔案。

通過設定persistentfalse,我們可以讓background在需要時被載入,在空閒時被解除安裝,從而釋放系統資源。唯一保持後臺指令碼持續活動的情況是擴充套件使用chrome.webRequest API來阻止或修改網路請求。webRequest API與非永續性後臺頁面不相容。

(4)popup

popup是點選瀏覽器工具欄上小圖示開啟的視窗,焦點離開頁面即關閉,可做臨時性互動。右鍵後點選“檢查”可開啟開發者工具進行除錯。

可以通過browser_actionpage_action進行設定。browser_action可作用於任何頁面,page_aciton可作用與部分頁面。如vue tools外掛,當檢測到頁面沒有使用vue時,外掛圖示顯示為不可用。

2、專案實踐

(1)環境搭建

專案主要使用vue-clivue-cli-plugin-chrome-ext進行開發,element-ui作為元件庫

1、安裝vue-cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli
複製程式碼

2、初始化一個專案

vue create demo
複製程式碼

3、進入專案目錄,安裝vue-cli-plugin-chrome-ext外掛。依次選擇外掛名稱、描述、版本號、使用js或ts

vue add vue-cli-plugin-chrome-ext
複製程式碼

4、清理檔案,刪除src/main.js, src/components, public/favicon.icopublic/index.html,最終目錄結構

demo
├── README.md
├── babel.config.js
├── package.json
├── node_modules
│   ├── ...
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── manifest.development.json
│   ├── manifest.production.json
│   ├── options
│   │   ├── App
│   │   │   └── App.vue
│   │   ├── index.html
│   │   └── index.js
│   └── popup
│       ├── App
│       │   └── App.vue
│       ├── index.html
│       └── index.js
├── vue.config.js
└── yarn.lock
複製程式碼

(2)執行專案

執行npm run build-watch,在根目錄生成dist資料夾,在chrome擴充套件頁面chrome://extensions/,勾選開發者模式,選擇“載入已解壓的擴充套件程式”,選擇dist資料夾,就可以新增擴充套件程式。新增好的外掛如下圖所示:

入門看看?Chrome外掛初窺與實踐

在位址列右側,也可以看到新增的外掛:

入門看看?Chrome外掛初窺與實踐

嘗試修改src/popup/App/App.vue檔案

<template>
  <div class="main_app">
    <h1>Hello World!</h1>
  </div>
</template>
複製程式碼

可以發現dist檔案被重新編譯,文字自動更新(注:如果修改了manifest.json,需要刪除外掛並重新安裝)

入門看看?Chrome外掛初窺與實踐

(3)開始開發

安裝element-ui

npm i element-ui -S
複製程式碼

為了減小檔案體積,按照element-ui官網所示,採取按需引用的方式

npm install babel-plugin-component -D
複製程式碼
// babel.config.js

module.exports = {
  // ...
  plugins: [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}


複製程式碼

popup頁面引入需要使用的元件

// src/popup/index.js

// ...
import {Input,Button,Row} from "element-ui";
Vue.use(Input)
Vue.use(Button)
Vue.use(Row)
// ...

複製程式碼

使用元件完成頁面的繪製

// src/popup/App/App.vue
<template>
  <div class="main">
    <el-row>
      <el-input v-model="form.mobile" type="number" placeholder="手機號"/>
    </el-row>
    <el-row>
      <el-input v-model="form.vericode" type="text" placeholder="驗證碼">
        <el-button slot="append" @click="sendVerifyCode">{{verifyText}}</el-button>
      </el-input>
    </el-row>
    <el-row>
      <el-button @click="login" type="primary">登陸</el-button>
    </el-row>
  </div>
</template>
<script>
  export default {
    name:'app',
    data() {
      return {
        form: {
          mobile: '',
          vericode: '',
        },
        token:'',
        verifyText:'獲取驗證碼',
      }
    },
    methods: {
      login() {}, // 登陸方法請按需實現
      sendVerifyCode () {}, // 獲取驗證碼方法請按需實現
    }
  }
</script>

複製程式碼

如圖所示,此時popup頁面繪製完成

入門看看?Chrome外掛初窺與實踐

現在,我們可以在popup頁面輸入資料,發起請求並獲取token,但是popup頁面無法訪問原頁面,所以我們需要將token傳遞給content,由它將token儲存在原頁面。

首先新建src/content/index.js檔案,並在manifest.development.json(生產環境在manifest.production.json)中新增content的配置

// src/manifest.deveploment.json
"content_scripts":
    [
        {
            "matches": ["http://*/*", "https://*/*"], // 按需要修改匹配的地址
            "js": ["js/content.js"],
            "run_at": "document_start"
        }
    ],

複製程式碼

修改vue.config.js,新增content打包設定

// vue.config.js
// 將content新增進chromeName即可
const chromeName = ["popup", "options", "content"];

複製程式碼

至此,content的配置基本完成,下面需要實現的是popupcontent之間的通訊

popup頁面可以通過tabs.sendMessagecontent傳遞資料。首先在manifest.development.json中新增使用tabs的許可權

// src/manifest.deveploment.json
{
  // ...
  "permissions":
    [
        "tabs"
    ],
}

複製程式碼

修改popup/App/App.vue,向content傳遞token

// src/popup/App/App.vue
// ...
		login() {
      	this.token = '這是token'
      	this.sendMsgToContent()
		},
    sendMsgToContent() { //向content傳送資訊,讓conent在頁面的sessionStroage中儲存token
        chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
          if (tabs.length !== 0) {
            chrome.tabs.sendMessage(tabs[0].id, this.token, (response) => {
              console.log(response)
            });
          }
        });
    }
  

複製程式碼

content/index.js中,接收token值並儲存

// src/content/index.js
chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        sessionStorage.clear()
        sessionStorage.setItem('token',request)
        sendResponse('收到請求');
    });

複製程式碼

在頁面嘗試一下,寫入成功

入門看看?Chrome外掛初窺與實踐

(4)問題記錄

popup的錯誤可以在視窗右鍵選擇‘檢查’

content可以直接在頁面控制檯檢視

chrome擴充套件程式裡的錯誤

  1. runtime不加入許可權可以使用,加入許可權會報錯"Permission 'runtime' is unknown or URL pattern is malformed"
  2. "Uncheked runtime.lastError.Could not establish connetcion.Receiving end does not exist"。重新安裝外掛並重新整理頁面,基本就可以了。

(5)打包使用

執行npm run build,生成dist資料夾,擴充套件程式頁面chrome://extensions/選擇“打包擴充套件程式”,可生成crx檔案。安裝時,可以將crx檔案直接拖入擴充套件程式頁面進行安裝。(高版本chrome可能會提示“該擴充套件程式未列在 Chrome 網上應用店中...”,親測把crx的字尾改為zip,再安裝)

參考連結

相關文章