更新程式碼

與其他問題無關的最新消息

這是三節內容的第一節,說明非擴充功能 Service Worker 的程式碼需要進行的變更。本節說明與其他問題無關的必要程式碼變更。接下來兩節將說明如何取代封鎖網路要求和提升安全性。

將 tabs.executeScript() 替換為 scripting.executeScript()

在 Manifest V3 中,executeScript() 會從 tabs API 移至 scripting API。除了實際變更程式碼,您也必須變更資訊清單檔案中的權限。

如要使用 executeScript() 方法,請準備下列項目:

  • "scripting" 權限。
  • 主機權限或 "activeTab" 權限。

scripting.executeScript() 方法與 tabs.executeScript() 的運作方式類似。兩者之間有幾項差異。

  • 舊方法只能接受單一檔案,新方法則可接受檔案陣列。
  • 您也會傳遞 ScriptInjection 物件,而非 InjectDetails。這兩者之間有許多差異。舉例來說,tabId 現在會以 ScriptInjection.target 的成員形式傳遞,而非方法引數。

這個範例說明如何執行這項操作。

Manifest V2
async function getCurrentTab() {/* ... */}
let tab = await getCurrentTab();

browser.tabs.executeScript(
  tab.id,
  {
    file: 'content-script.js'
  }
);

在背景指令碼檔案中。

Manifest V3
async function getCurrentTab()
let tab = await getCurrentTab();

browser.scripting.executeScript({
  target: {tabId: tab.id},
  files: ['content-script.js']
});

在擴充功能 Service Worker 中。

將 tabs.insertCSS() 和 tabs.removeCSS() 替換為 scripting.insertCSS() 和 scripting.removeCSS()

在 Manifest V3 中,insertCSS() 和 removeCSS() 會從 tabs API 移至 scripting API。除了變更程式碼,您也必須變更資訊清單檔案中的權限:

  • "scripting" 權限。
  • 主機權限或 "activeTab" 權限。

scripting API 上的函式與 tabs 上的函式類似。兩者之間有幾項差異。

  • 呼叫這些方法時,請傳遞 CSSInjection 物件,而非 InjectDetails。
  • tabId 現在會以 CSSInjection.target 成員的形式傳遞,而非做為方法引數。

這個範例說明如何為 insertCSS() 執行這項操作。removeCSS() 的程序相同。

Manifest V2
browser.tabs.insertCSS(tabId, injectDetails, () => {
  // callback code
});

在背景指令碼檔案中。

Manifest V3
const insertPromise = await browser.scripting.insertCSS({
  files: ["style.css"],
  target: { tabId: tab.id }
});
// Remaining code. 

在擴充功能 Service Worker 中。

以「動作」取代「瀏覽器動作」和「頁面動作」

在 Manifest V2 中,瀏覽器動作和網頁動作是不同的概念。雖然一開始的角色不同,但隨著時間推移,兩者之間的差異逐漸縮小。在 Manifest V3 中,這些概念會整合成 Action API。這需要變更 manifest.json 和擴充功能程式碼,與您在 Manifest V2 背景指令碼中放置的內容不同。

資訊清單 V3 中的動作與瀏覽器動作最為相似,但 action API 不會提供 hide() 和 show(),就像 pageAction 一樣。如果仍需要網頁動作,您可以使用宣告式內容模擬這些動作,或使用分頁 ID 呼叫 enable() 或 disable()。

將「browser_action」和「page_action」替換為「action」

在 manifest.json 中,將 "browser_action" 和 "page_action" 欄位替換為 "action" 欄位。請參閱有關 "action" 欄位的參考資料。

Manifest V2
{
  ...
  "page_action": { ... },
  "browser_action": {
    "default_popup": "popup.html"
   }
  ...
}
Manifest V3
{
  ...
  "action": {
    "default_popup": "popup.html"
  }

  ...
}

以 action API 取代 browserAction 和 pageAction API

如果 Manifest V2 使用 browserAction 和 pageAction API,現在應改用 action API。

Manifest V2
browser.browserAction.onClicked.addListener(tab => { ... });
browser.pageAction.onClicked.addListener(tab => { ... });
Manifest V3
browser.action.onClicked.addListener(tab => { ... });

以 Promise 取代回呼

在 Manifest V3 中,許多擴充功能 API 方法都會傳回 Promise。Promise 是非同步方法傳回值的 Proxy 或預留位置。如果您從未使用過 Promise,可以在 MDN 上瞭解相關資訊。本頁說明在 Chrome 擴充功能中使用這些 API 時需要注意的事項。

為了確保回溯相容性,在新增 Promise 支援後,許多方法仍會繼續支援回呼。請注意,您無法在同一個函式呼叫中使用這兩者。如果您傳遞回呼,函式不會傳回 Promise;如要傳回 Promise,請勿傳遞回呼。部分 API 功能 (例如事件監聽器) 仍需回呼。如要檢查方法是否支援 Promise,請在 API 參考資料中尋找「Promise」標籤。

如要從回呼轉換為 Promise,請移除回呼並處理傳回的 Promise。以下範例取自選用權限範例,具體來說是 newtab.js。回呼版本會顯示範例對 request() 的呼叫,以及回呼的樣子。請注意,Promise 版本可能會以 async 和 await 重新編寫。

回撥電話
browser.permissions.request(newPerms, (granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});
Promise
const newPerms = { permissions: ['topSites'] };
browser.permissions.request(newPerms)
.then((granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});

取代預期 Manifest V2 背景情境的函式

其他擴充功能環境只能透過訊息傳遞與擴充功能服務工作人員互動。因此,您需要替換預期背景環境的呼叫,具體來說:

  • browser.runtime.getBackgroundPage()
  • browser.extension.getBackgroundPage()
  • browser.extension.getExtensionTabs()

擴充功能指令碼應使用訊息傳遞功能,在 Service Worker 和擴充功能的其他部分之間進行通訊。目前,您可以使用 sendMessage(),並在擴充功能 Service Worker 中實作 browser.runtime.onMessage,達成這個目標。從長遠來看,您應計畫以 postMessage() 和服務工作人員的訊息事件處理常式,取代這些呼叫。

替換不支援的 API

Manifest V3 中需要變更的方法和屬性如下。

Manifest V2 方法或屬性 替換成
browser.extension.connect() browser.runtime.connect()
browser.extension.connectNative() browser.runtime.connectNative()
browser.extension.getExtensionTabs() browser.extension.getViews()
browser.extension.getURL() browser.runtime.getURL()
browser.extension.lastError 如果方法傳回 Promise,請使用 promise.catch()
browser.extension.onConnect browser.runtime.onConnect
browser.extension.onConnectExternal browser.runtime.onConnectExternal
browser.extension.onMessage browser.runtime.onMessage
browser.extension.onRequest browser.runtime.onMessage
browser.extension.onRequestExternal browser.runtime.onMessageExternal
browser.extension.sendMessage() browser.runtime.sendMessage()
browser.extension.sendNativeMessage() browser.runtime.sendNativeMessage()
browser.extension.sendRequest() browser.runtime.sendMessage()
browser.runtime.onSuspend (背景指令碼) 擴充功能服務工作人員不支援這項功能。請改用 beforeunload 文件事件。
browser.tabs.getAllInWindow() browser.tabs.query()
browser.tabs.getSelected() browser.tabs.query()
browser.tabs.onActiveChanged browser.tabs.onActivated
browser.tabs.onHighlightChanged browser.tabs.onHighlighted
browser.tabs.onSelectionChanged browser.tabs.onActivated
browser.tabs.sendRequest() browser.runtime.sendMessage()
browser.tabs.Tab.selected browser.tabs.Tab.highlighted