chrome插件background、content、popup的通信


[入門系列3 - background、content、popup的通信 - 掘金](https://juejin.cn/post/6844903985711677453 )]

前言

😋😋😋嘿,各位爺好~~

前面兩節簡單的總結了一些關於什么是瀏覽器插件,以及瀏覽得的manifest.json文件配置。同時在后續也給插件增加了頁面和邏輯,說明了backgroundpopupcontent三個字段的具體使用。

不同字段對應着不同的作用,協作構成了插件的強大功能。合作就得溝通,就像Electron的主進程和渲染進程通信,那它們之間是如何通信的呢?

插件的架構體系

插件呢,必須具有存在位於瀏覽器工具欄中的圖標,工具欄圖標允許輕松訪問,並使用戶了解安裝了哪些插件。大多數用戶通過單擊圖標,使用其彈出窗口進行交互,比如CORS跨域插件,谷歌翻譯插件等等。

插件的體系結構是取決於其功能,但大多數功能強大的插件包括以下多個組件:

  • manifest
  • background scripts
  • ui elements ==> popup
  • content scripts
  • optional page

備注:就像插件允許用戶自定義Chrome瀏覽器一樣,optional page可以自定義插件。在chrome40以前,使用options_page配置;在chrome40以后,則使用options_ui配置。

組件的backgroundpopupcontent三個字段整體關系圖如下:

 

通信

插件的不同組件之間通常需要彼此通信,不同的HTML頁面可以使用chrome.extension方法找到彼此,例如getViews()和getBackgroundPage()。一旦頁面引用了其他擴展頁面,第一個頁面就可以調用其他頁面上的函數並操縱它們的DOM。此外,插件的所有組件還可以使用storage API存儲值,並使用消息傳遞進行通信。

而對於組件backgroundpopupcontent,具體通信可以看下圖:

 

 

可以看到存在6種通信路徑:

  1. popupbackground之間的通信
    1. backgroundpopup發送消息
    2. popupbackground發送消息
  2. backgroundcontent之間的通信
    1. backgroundcontent發送消息
    2. contentbackground發送消息
  3. popupcontent之間的通信
    1. popupcontent發送消息
    2. contentpopup發送消息

腳本權限

我們已經了解了存在的幾種通信路徑,通信意味着各種API的相互調用,因此在實踐之前,也需要去了解一點關於chrome 插件的腳本權限

腳本的類型決定着腳本存在什么權限:比如Chrome APIDOM 訪問跨域訪問原頁面JS訪問,具體如圖:

 

=====> 圖使用markdown編輯 好了,了解了權限以后,就知道什么腳本可以使用何種API來實現信息傳遞,接下來就嘗試去打通每一關吧。

popupbackground之間的通信

首先,給一個大致通信圖。關於content scriptpopup scriptbackground script,它們之間的通信總體概覽圖如下:

 

開始吧。還是和以前一樣,新建插件文件夾,增加必須的manifest.json和基本文件。

backgroundpopup發送消息

插件的background,對於瀏覽器只存在一個,而對於popup,不同的 tab 就會存在一個前端,如果background需要給不同前端發送信息,就需要特殊的tab id。這里是針對backgroundpopup傳遞信息。

background.js 添加代碼:

function toPopup() {
    alert('to popup!')
}
復制代碼

popup.js 添加代碼:

const bg = chrome.extension.getBackgroundPage()
document.getElementById('rBgInfo').onclick = function() {
    bg.toPopup()
}
復制代碼

popup.html引入popup.js,並添加id為rBgInfo的按鈕,安裝插件,點擊按鈕,如果彈窗如下樣式,則表明成功。

 

 

popupbackground發送消息

background => popup 是通過getBackgroundPage,而popup => background是通過getViews

下面就來瞧一下

使用長連接

popup.js增加如下代碼:

// 使用長連接
let port = chrome.extension.connect({
    name: 'popup-name'
})

// 使用postMs 發送信息
port.postMessage('給 background 傳遞信息~')

// 接收信息
port.onMessage.addListener(msg => {
    console.log('接收的信息:', msg)
})
復制代碼

background.js 增加如下代碼:

// 獲取所有 tab
const pups = chrome.extension.getViews({
    type: 'popup'
}) || []

// 輸出第一個使用插件頁面的url
if (pups.length) {
    console.log(pups[0].location.href)
}
復制代碼

點擊插件刷新按鈕,點擊【背景頁】按鈕,可以看到每次點擊一下插件圖標,就會發送一次信息。

 

這也告訴了 chrome 插件的另一個機制:點擊圖標出現和隱藏popup彈窗頁面,實際上是對整個頁面的銷毀,類似於關閉網頁,而不是切換網頁。(很重要的哦)

操作 DOM

除了信息傳遞,background可能也需要對popup.html的頁面進行操作,比如檢測到當前是萬聖節🎃,給插件頁面添加個happy halloween

首先給popup.html增加一個text

<p id="pbText">不是萬聖節</p>
復制代碼

然后只需要在background.js中如下處理:

// 使用長連接 - 監聽 popup 傳遞來的消息
chrome.extension.onConnect.addListener(port => {
    console.log('連接中------------')
    port.onMessage.addListener(msg => {
        console.log('接收消息:', msg)
        getAll()
        port.postMessage('popup,我收到了你的信息~')
    })
})

// 獲取所有 tab
function getAll() {
    const views = chrome.extension.getViews({
        type: 'popup'
    })

    for (let o of views) {
        console.log(111)
        o.document.getElementById('pbText').innerHTML = "萬聖節🎃快樂"
    }
}
復制代碼

添加getAll()函數,將函數防止長連接即可。這里主要想展示chrome.extension.getViews函數的使用。

刷新插件,點擊插件圖標,就會彈窗如下頁面了:

 

 

popupcontent之間的通信

有了backgroundpopup,下面需要做的就是創建一個content頁面。

manifest添加下列配置

{
    ...
    "content_scripts": [
        {
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "content.js"
            ]
        }
    ]
}
復制代碼

contentpopup發送消息

首先在content.js添加如下代碼:

// Chrome提供的大部分API是不支持在content_scripts中運行
// sendMessage onMessage 是可以使用
chrome.runtime.sendMessage({
    info: "我是 content.js"
}, res => {
    // 答復
    alert(res)
})
復制代碼

代碼負責發送信息和接收反饋,然后給popup.js添加:

chrome.runtime.onMessage.addListener((req,sender, sendResponse) => {
    sendResponse('我收到了你的來信')
    console.log('接收了來自 content.js的消息', req.info)
})
復制代碼

代碼負責接收消息和發送反饋。

刷新插件,點擊插件按鈕,打開一個頁面,保持插件popup處於活躍狀態(上面講了哈~,插件關閉等於頁面銷毀),然后刷新頁面,會發現瀏覽器彈出彈窗:

 

 

最后,右鍵插件圖標,點擊“審查彈窗內容”,可以看到content.jspopup.jsconsole.log日志(👻這等於告訴您如何調試插件~)

 

 

彈窗說明我們的程序是成功運行的,日志打印表明我們的通信是成功的,現在我們已經知道了contentpopup發送消息。

popupcontent發送消息

其實上面已經告訴了popupcontent發送信息了,但畢竟不是popup主動地,談戀愛了,肯定需要主動一些了。

popup添加如下代碼,放入rBgInfo按鈕點擊事件:

// popup ---> content
chrome.tabs.query({
    active: true,
    currentWindow: true
}, (tabs) => {
    let message = {
        info: '來自popup的情書💌'
    }
    chrome.tabs.sendMessage(tabs[0].id, message, res => {
        console.log('popup=>content')
        console.log(res)
    })
})
復制代碼

寄送一封信,content得接收信:

// get popup2content info
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log(request.info)
    sendResponse('我收到了你的情書,popup~')
})
復制代碼

點擊插件刷新按鈕,打開頁面,點擊彈窗的rBgInfo按鈕,日志打印如下:

 

 

關於popupcontent的通信又又又成功了~

backgroundcontent之間的通信

backgroundcontent之間的通信與popupcontent類似的,寫者就不寫demo了,與上面一樣。

長連接與短連接

在上面的一些demo中,可以看到通信使用了兩個函數,一個就是sendMessage,另一個就是connect,其實這兩個分別對應着不同的連接方式:

  • 長連接: chrome.tabs.connectchrome.runtime.connect
  • 短連接: chrome.tabs.sendMessage

總結

了解了腳本之前的通信以后,才算真正的入門了,希望各位能學到點什么。下面關於chrome 插件的博客,可能會涉及到具體真正插件開發的實踐了,更新或許會慢一點,見諒❤❤❤!

備注:這幾天工作較忙,寫博客都得擠時間了。希望大家也能在工作之余過好每天,謝謝時光~


作者:Rabbitzzc
鏈接:https://juejin.cn/post/6844903985711677453
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM