更新程式碼

與其他問題無關的更新內容

這是三個部分的第一節,說明不屬於擴充功能服務 Worker 的程式碼需要變更。本節說明程式碼變更的必要性,與其他問題無關。接下來兩節將說明取代封鎖網路要求的方式提升安全性

將 tab.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();

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

位於背景指令碼檔案中。

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

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

在擴充功能 Service Worker 中。

將 tab.insertCSS() 和 tab.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
chrome.tabs.insertCSS(tabId, injectDetails, () => {
  // callback code
});

位於背景指令碼檔案中。

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

在擴充功能 Service Worker 中。

用動作取代瀏覽器動作和網頁動作

在 Manifest V2 中,瀏覽器動作和網頁動作是不同的概念。雖然最初是不同的角色,但兩者之間的差異會隨時間而減少。在 Manifest V3 中,這些概念已併入 Action API。這需要變更 manifest.json 和擴充功能程式碼,與 Manifest V2 背景指令碼中的程式碼不同。

Manifest 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"
  }

  ...
}

將 BrowserAction API 和 pageAction API 替換成 Action API

Manifest V2 使用 browserActionpageAction API 的位置,現在應使用 action API。

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

以 promise 取代回呼

在 Manifest V3 中,許多擴充功能 API 方法會傳回承諾。Promise 是非同步方法回傳值的 Proxy 或預留位置。如果您從未使用過 Promise,可以參閱 MDN 相關資訊。本頁面將說明在 Chrome 擴充功能中使用這些項目的須知。

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

如要將回呼轉換為 promise,請移除回呼並處理傳回的承諾。下列範例取自選用權限範例 (newtab.js)。回呼版本會顯示透過回呼對 request() 呼叫的模樣。請注意,promise 版本可以使用 async 重新編寫並等待。

Callback
chrome.permissions.request(newPerms, (granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});
承諾
const newPerms = { permissions: ['topSites'] };
chrome.permissions.request(newPerms)
.then((granted) => {
  if (granted) {
    console.log('granted');
  } else {
    console.log('not granted');
  }
});

替換預期需要 Manifest V2 背景內容的函式

其他擴充功能結構定義只能透過使用訊息傳送功能與擴充功能服務工作站互動。因此,您必須替換預期背景情境的通話,尤其是:

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

擴充功能指令碼應使用訊息傳遞功能,在 Service Worker 和擴充功能的其他部分之間進行通訊。目前要求使用 sendMessage(),並在擴充功能服務工作站中實作 chrome.runtime.onMessage。長期下來,您應該規劃將這些呼叫替換為 postMessage() 和服務工作站的訊息事件處理常式

替換不支援的 API

下列方法和屬性必須在 Manifest V3 中進行變更。

Manifest V2 方法或屬性 取代憑證
chrome.extension.connect() chrome.runtime.connect()
chrome.extension.connectNative() chrome.runtime.connectNative()
chrome.extension.getExtensionTabs() chrome.extension.getViews()
chrome.extension.getURL() chrome.runtime.getURL()
chrome.extension.lastError 如果方法傳回保證,則使用 promise.catch()
chrome.extension.onConnect chrome.runtime.onConnect
chrome.extension.onConnectExternal chrome.runtime.onConnectExternal
chrome.extension.onMessage chrome.runtime.onMessage
chrome.extension.onRequest chrome.runtime.onRequest
chrome.extension.onRequestExternal chrome.runtime.onMessageExternal
chrome.extension.sendMessage() chrome.runtime.sendMessage()
chrome.extension.sendNativeMessage() chrome.runtime.sendNativeMessage()
chrome.extension.sendRequest() chrome.runtime.sendMessage()
chrome.runtime.onSuspend (背景指令碼) 擴充功能 Service Worker 不支援這項功能。請改用 beforeunload 文件事件。
chrome.tabs.getAllInWindow() chrome.tabs.query()
chrome.tabs.getSelected() chrome.tabs.query()
chrome.tabs.onActiveChanged chrome.tabs.onActivated
chrome.tabs.onHighlightChanged chrome.tabs.onHighlighted
chrome.tabs.onSelectionChanged chrome.tabs.onActivated
chrome.tabs.sendRequest() chrome.runtime.sendMessage()
chrome.tabs.Tab.selected chrome.tabs.Tab.highlighted