陈颂光
全栈工程师,能够独立开发从解释器到网站和桌面/移动端应用的各类软件。
关注我的 GitHub

编写浏览器插件:适用于Chrome、Firefox、Edge和Opera

浏览器插件(或称扩展)可以修改浏览器的行为,比如可以屏蔽广告、防止跟踪、下载视频、翻译网页、增加搜索引擎等等。在过往不同浏览器有互不兼容的插件机制,但现在包括Chrome、Firefox、Edge和Opera在内的主流浏览器都在某程度上支持了WebExtensions API,因而我们能轻松地编写同时适用于多个浏览器的插件。

流程

我们演示如何制作一个简单的插件,它在开启时可以屏蔽网页中的视频。

首先,我们在一个新的目录下编写一个清单文件manifest.json描述扩展的元数据:

{
	"manifest_version":2,
	"name":"VideoBlock",
	"description":"Block all videos",
	"version":"0.1",
	"permissions":["webRequest","webRequestBlocking","<all_urls>"], 
	"background":{"scripts":["background.js"]},
	"browser_action":{"default_icon":{"32":"icons/off.png"}}
}

在这例子中:

  • 清单语法版本为2(不要改)
  • 扩展名为VideoBlock
  • 简介为Block all videos
  • 版本号为0.1
  • 需要权限为可拦截到所有URI的请求
  • 加载扩展后马上运行脚本background.js
  • 在浏览器工具栏中加入一个按钮,默认图标为icons/off.png

其次我们编写background.js

var blocking=false;
browser.webRequest.onBeforeRequest.addListener(function(requestDetails){
	if(blocking){
		return {redirectUrl:requestDetails.url};
	}else{
		return {redirectUrl:null};
	}
},{urls:["<all_urls>"],types:["media"]},["blocking"]);
browser.browserAction.onClicked.addListener(function(){
	if(blocking){
		browser.browserAction.setIcon({path: "icons/off.png"});
	}else{
		browser.browserAction.setIcon({path: "icons/on.png"});
	}
	blocking=!blocking;
});

这脚本中用变量blocking记录屏蔽功能当前是否已启用,然后监视两个事件:

  • 当有类型为media的请求且屏蔽功能启用时屏蔽之
  • 当按钮被点击时启用或关闭屏蔽功能,同时通过修改按钮图标反映新状态

接着我们在下画两个32像素高和宽的图标icons/off.pngicons/on.png分别用于关闭和开启屏蔽功能时的图标。

现在我们让浏览器加载这个扩展:

  • 在Firefox中
    1. 访问URLabout:debugging
    2. 选中启用附加组件调试
    3. 点击载入临时附加组件
    4. 选择manifest.json文件
  • 在Chrome中
    1. 访问URLchrome://extensions
    2. 选中Developer Mode
    3. 点击LOAD UNPACKED
    4. 选择manifest.json所在文件夹
  • 在Edge中
    1. 访问URLabout:flags
    2. 选中Enable extension developer features
    3. 点击More (...)
    4. 点击Extensions
    5. 点击Load extension
    6. 选择manifest.json所在文件夹

加载后点击扩展在工具栏中的按钮,再打开一个带视频的网页,应该就会发现视频播放不了。

最后我们还可以把扩展发布到网上,让别人通过浏览器的扩展中心发现并安装我们开发的扩展:

清单

每个扩展都有一个描述元数据的清单,它是直接位于扩展目录、名为manifest.json的JSON文件,常见字段如下:

必要性 用途 格式例子
name 必须 给用户看的扩展名称,不超过45个字符 "Video blocker"
version 必须 版本号,由一到四个用句点分隔的整数组成 "1""1.0""2.10.2""3.1.2.4567"
default_locale 当且仅当扩展目录有子目录_locales 存放默认字符串的_locales子目录名 en
description 可选 给用户看的扩展简介 "Block all videos"
icons 可选 扩展不同大小(以px为单位)的图标文件位置 {"24":"small.jpg","48":"medium.jpg"}
developer 可选 开发者的名称和/或网址 {"name": "Bighard", "url": "https://www.bighard.com"}
browser_action 可选 加到浏览器工具栏的按钮,可指定图标、提示和点击时打开的对话框页面,不能与page_action共存 {"default_icon":{"16": "button/geo-16.png","32":"button/geo-32.png"},"default_title": "Whereami?","default_popup": "popup/geo.html"}
page_action 可选 加到浏览器工具栏的按钮,可指定图标、提示和点击时打开的对话框页面,不能与browser_action共存 同上
browser_specific_settings 可选 浏览器特定的值 {"gecko":{"strict_min_version": "57.0"}}(表示要求Firefox的版本至少为57才能安装)
background 可选 浏览器加载扩展后即开始运行的脚本,还可指定运行于的页面和是否保持这页面于已加载状态以记忆状态 {"page": "background.html","scripts": ["background.js"],"persistent":true}
content_scripts 可选 自动把js指定的脚本和/或css指定的样式表加入每个页面(all_framesfalse时则修改模式matches指定的页面或不修改模式exclude_matches指定的页面)由run_at指定的位置"document_start""document_end""document_idle" {"all_frames": <boolean>,"css": [...],"exclude_matches": [...],"js": [...],"matches": [...],"run_at": "document_end"}
content_security_policy 可选 防止意外执行恶意代码的内容安全策略 "script-src 'self'; object-src 'self';"
options_page 可选 选项页 "options/options.html"
manifest_version 可选 清单版本,一般为2 2
web_accessible_resources 可选 容许页面通过browser.extension.getURL()访问的资源 ["images/useless.png"]
permissions 可选 需要的额外权限,包括危险API和作危险访问(如绕过同源策略访问有关页面、用tabs.executeScript向有关页面插入脚本、用webRequestAPI从有关页面接收事件)的URL ["activeTab","contextMenus","tabs","webNavigation","webRequestBlocking","*://*.w3.org/*","<all_urls>"]
required_keys 可选 要求浏览器支持指定字段才安装 ["theme"]
externally_connectable 可选 接受来自其它扩展或URL模式的消息 ["ids": [],"matches": []]
author 可选 作者 Zhang
chrome_settings_overrides 可选 主页和搜索引擎 {"homepage":"https://www.viewfact.org/","search_provider":{"name":"睇料","search_url":"https://www.viewfact.org/search?q={searchTerms}","keyword":"viewfact","favicon_url":"https://www.viewfact.org/favicon.ico"}}
chrome_url_overrides 可选 特殊页面如新标签页 {"newtab": "my-new-tab.html"}
commands 可选 命令(包括特殊命令_execute_browser_actionexecute_page_action_execute_sidebar_action)的描述和键盘快捷键(对不同平台"default""mac""linux""windows""chromeos""android""ios"可指定不同快捷键) {"toggle-feature":{"suggested_key":{"default": "Ctrl+Shift+Y","linux": "Ctrl+Shift+U"},"description": "Send a 'toggle-feature' event"}}
devtools_page 可选 开发者工具 "devtools/my-page.html"
homepage_url 可选 扩展的主页 "https://example.org/my-addon"
incognito 可选 区分隐私窗口 "spanning"(隐私和非隐私窗口的事件对扩展可见)、 "split"(运行两套扩展)、"not_allowed"
offline_enabled 可选 是否预期在离线时使用 true
omnibox 可选 用户在地址栏输入指定关键词后,其余部分会发给应用 {"keyword": "mdn"}
optional_permissions 可选 运行时可能请求用户批准的权限 []
options_ui 可选 选项页 {"page": "options/options.html","open_in_tab":false,"browser_style":true}
name 可选 给用户看的扩展简称,不超过12个字符 "NoVideo"
theme 可选 外观主题 {"images":{"headerURL": "images/sun.jpg"},"colors": {"bookmark_text":[0,0,0],"frame_inactive":[0,0,0],"ntp_background":[0,0,0],"ntp_text":[0,0,0],"tab_background_text":[0,0,0],"tab_text":[0,0,0],"toolbar": [0,0,0]},"properties":{}}
version_name 可选 给人看的版本号 "0.1 beta"

国际化与本地化

为了让扩展支持多种语言,首先找出扩展中所有需要翻译的信息加以国际化,方法是为它们分别起个互不相同的名字(符合正则表达式[A-Za-z0-9@_]+?),然后按场合把信息替换为:

  • 若在清单或样式表中,则替换为__MSG_名字__
  • 若在脚本中,则替换为browser.i18n.getMessage('名字',字符串或其数组)
预定义的信息名 说明
@@extension_id 扩展ID,不能用于清单
@@ui_locale 当前地区
@@bidi_dir 当前地区的文字方向:"ltr""rtl"
@@bidi_reversed_dir 当前地区的文字反方向:"ltr""rtl"
@@bidi_start_edge 当前地区的文字方向:"left""right"
@@bidi_end_edge 当前地区的文字反方向:"right""left"

接下来是本地化,方法是在扩展目录的子目录_locales下为每种语言创建分别创建子目录(目录名为语言代码语言代码_地区代码),再分别在这些子目录创建JSON文件。JSON文件的字段名为各消息的名字,值则是消息模板:

  • 对于没有参数的消息模板,形如"extensionName":{"message": "Image Blocker","description": "Name of the extension"}
  • 对于有参数的消息模板
    • 可以用$序号指代位置参数,形如"of":{"message": "$2的$1","description": "of something"}
    • 也可以给参数名字,形如"{"message": "You clicked $URL$.","description":"Tells the user which link they clicked.","placeholders":{"url":{"content":"$1","example":"https://developer.mozilla.org"}}}

API

浏览器开放给扩展用Javascript调用的API大多在全局对象(即window的字段)browser中,用WebIDL可以如下描述各主要类型:

[CheckAnyPermissions="browserExt"]
interface BrowserExtGlobal {
    readonly attribute Browser browser;
};
Window implements BrowserExtGlobal;

[NoInterfaceObject] 
interface Browser { 
};
dictionary BrowserExtIcon {
    DOMString path;
    DOMString size;
};
typedef sequence<BrowserExtIcon> BrowserExtIconArray;
dictionary BrowserExtDeveloper {
    DOMString name;
    DOMString? url;
};
dictionary BrowserExtBrowserOrPageAction {
    BrowserExtIcon? defaultIcon; 
    DOMString? defaultPopup;
    DOMString? defaultTitle;
};
dictionary BrowserExtKeyValue {
    DOMString key;
    DOMString? value;
};
dictionary BrowserExtBrowserSpecificSettings {
    DOMString browserName;
    sequence<BrowserExtKeyValue> keyValue;
};
dictionary BrowserExtBackroundOrEvent {
    DOMString? page;
    boolean persistent;
    sequence<DOMString>? scripts;
};
dictionary BrowserExtContentScripts {
    boolean allFrames;
    sequence<DOMString>? css;
    sequence<DOMString>? excludeMatches;
    sequence<DOMString>? js;
    sequence<DOMString> matches;
    DOMString? runAt;
};
dictionary BrowserExtManifest {
    BrowserExtBackroundOrEvent? background;
    BrowserExtBrowserOrPageAction? browserAction;
    BrowserExtBrowserSpecificSettings? browserSpecificSettings;
    BrowserExtContentScripts? contentScripts;
    DOMString? contentSecurityPolicy;
    DOMString? defaultLocale;
    DOMString? description;
    BrowserExtDeveloper? developer;
    BrowserExtIconArray? icons;
    DOMString? manifestVersion;
    DOMString name;
    DOMString? optionsPage;
    BrowserExtBrowserOrPageAction? pageAction;
    sequence<DOMString>? permissions;
    sequence<DOMString>? requiredKeys;
    DOMString? version;
    sequence<DOMString> webAccessibleResources;
};
[NoInterfaceObject, Exposed=(Window,ContentScript), CheckAnyPermissions="browserExt"]
interface BrowserExtEvent {
    void    addListener(Function callback);
    void    removeListener(Function callback);
    boolean hasListener(Function callback);
    boolean hasListeners();
};

在WebIDL中,我们用Exposed属性描述可用上下文(Window表示backgroundbrowser_actionpage_actionoptions_page等字段引入的脚本,ContentScript表示content_scripts字段引入的脚本)。

BrowserAction

browser.browserAction给出了浏览器按钮的API:

dictionary BrowserExtBrowserActionDefaults {
    BrowserExtIconArray? defaultIcon;
    DOMString? defaultPopup;
    DOMString?  defaultTitle;
};
partial dictionary BrowserExtManifest {
        BrowserExtBrowserActionDefaults? browserActionDefaults;
};
typedef sequence<byte> BrowserExtColorArray;
dictionary BrowserExtTabIdDetails {
    long tabId;
};
dictionary BrowserExtBadgeColorArrayTabId {
    BrowserExtColorArray color;
    long tabId;
};
dictionary BrowserExtBadgePathTabId {
    DOMString path;
    long tabId;
};
dictionary BrowserExtBadgeTextTabId {
    long tabId;
    DOMString text;
};
dictionary BrowserExtBadgeTabIdPopup {
    DOMString popupHTMLFileName;
    long tabId;
};
callback BrowserExtBrowserActionOnClickedCallback = void (BrowserExtTabsTab tab);
[NoInterfaceObject]
interface BrowserExtBrowserAction {
    void disable(long tabId);
    void enable(long tabId);
    Promise<BrowserExtColorArray> getBadgeBackgroundColor(BrowserExtTabIdDetails details);
    Promise<DOMString?> getBadgeText(BrowserExtTabIdDetails details);
    Promise<DOMString?> getPopup(BrowserExtTabIdDetails details);
    BrowserExtEvent onClicked(BrowserExtBrowserActionOnClickedCallback callback);
    void setBadgeBackgroundColor(BrowserExtBadgeColorArrayTabId details);
    void setBadgeText(BrowserExtBadgeTextTabId details);
    Promise<void> setIcon(BrowserExtBadgePathTabId details);
    void setPopup(BrowserExtBadgeTabIdPopup details);
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtBrowserAction"]
interface BrowserExtBrowserActionAPI {
    readonly attribute BrowserExtBrowserAction browserAction; 
};
Browser implements BrowserExtBrowserActionAPI;

ContextMenus

browser.contextMenus给出了上下文菜单的API:

enum BrowserExtContextType { "all", "audio", "browser_action", "editable", "frame", "image", "link", "page", "page_action", "selection", "video" };
enum BrowserExtItemType { "checkbox","normal","radio","separator" };
dictionary BrowserExtContextMenuCreateDetails {
    boolean checked;
    sequence<ContextType>? contexts;
    sequence<DOMString>? documentUrlPatterns;
    boolean enabled;
    DOMString? id;
    Function onclick;
    (long or DOMString?) parentId;
    sequence<DOMString>? targetUrlPatterns;
    DOMString? title;
    DOMString? type;
};
dictionary BrowserExtContextMenuUpdateDetails {
    boolean checked;
    sequence<BrowserExtContextType>? contexts;
    sequence<DOMString>? documentUrlPatterns;
    boolean enabled;
    Function onclick;
    long parentId;
    sequence<DOMString>? targetUrlPatterns;
    DOMString? title;
    ItemType? type;
};
dictionary BrowserExtContextMenuOnClickedDetails {
    boolean checked;
    boolean editable;
    long frameId;
    DOMString? frameUrl;
    DOMString? linkUrl;
    DOMString? mediaType;
    (long or DOMString) menuItemId;
    DOMString? pageUrl;
    (long or DOMString?) parentMenuItemId;             
    DOMString? selectionText;
    DOMString? srcUrl;
    boolean wasChecked;
};
callback BrowserExtContextMenuOnClickedCallback = void (BrowserExtContextMenuOnClickedDetails details, BrowserExtTabsTab tab);
[NoInterfaceObject]
interface BrowserExtContextMenus {
    Promise<long> create(BrowserExtContextMenuCreateDetails details);
    BrowserExtEvent onClicked(BrowserExtContextMenuOnClickedCallback callback);
	Promise<void> remove((long or DOMString) itemId);
    Promise<void>  removeAll();
    Promise<void>  update((long or DOMString) itemId, BrowserExtContextMenuUpdateDetails details);
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtContextMenus"]
interface BrowserExtContextMenusAPI {
    readonly attribute BrowserExtContextMenus contextMenus; 
};
Browser implements BrowserExtContextMenusAPI;

i18n

browser.i18n给出了国际化的API:

[NoInterfaceObject]
interface BrowserExtI18n {
    DOMString getMessage(DOMString messageName, sequence<DOMString?>? substitutions);
};
[NoInterfaceObject, Exposed=(Window,ContentScript), CheckAnyPermissions="browserExt"] 
interface BrowserExtI18nAPI {
        readonly attribute BrowserExtI18n i18n;
};
Browser implements BrowserExtI18nAPI;
partial dictionary BrowserExtManifest {
    DOMString? defaultLocaleValue;
};

pageAction

browser.pageAction给出了页面按钮的API:

dictionary BrowserExtPageActionDefaults {
    BrowserExtIconArray? defaultIcon;
    DOMString? defaultPopup;
    DOMString?  defaultTitle;
};
partial dictionary BrowserExtManifest {
    BrowserExtPageActionDefaults? pageActionDefaults;
};
dictionary BrowserExtBadgePath {
    DOMString path;
};
callback BrowserExtPageActionOnClickedCallback = void (BrowserExtTabsTab tab);
interface BrowserExtPageAction {
    Promise<DOMString?> getPopup(BrowserExtTabIdDetails details);
    Promise<DOMString?> getTitle(BrowserExtTabIdDetails details);
    void hide(long tabId);
    BrowserExtEvent onClicked(BrowserExtPageActionOnClickedCallback callback);
    Promise<void> setIcon(BrowserExtBadgePath path);
    void setPopup(BrowserExtBadgePathTabId details);
    void setTitle(BrowserExtBadgeTextTabId details);
    void show(long tabId);
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtPageAction"]
interface BrowserExtPageActionAPI {
    readonly attribute BrowserExtPageAction pageAction; 
};
Browser implements BrowserExtPageActionAPI;

runtime

browser.runtime给出了运行时的API(用于扩展与页面相互通信):

enum BrowserExtRuntimeOnInstalledReason {"browser_update", "extension_install", "extension_update"};
dictionary BrowserExtRuntimeOnInstalledDetails {
    BrowserExtRuntimeOnInstalledReason reason;
    DOMString? previousVersion;
    DOMString? id;
};
dictionary BrowserExtRuntimePort {
    Function disconnect;
    DOMString name;
    object onDisconnect;
    object onMessage;
    Function postMessage;
    BrowserExtRuntimeMessageSender? sender;
};
dictionary BrowserExtRuntimeMessageSender {
    DOMString? id;
    long frameId;
    BrowserExtTabsTab? tab;
    DOMString? url;
};
callback BrowserExtRuntimeOnConnectCallback = void (BrowserExtRuntimePort port);
callback BrowserExtRuntimeOnInstalledCallback = void (BrowserExtRuntimeOnInstalledDetails details);
callback BrowserExtRuntimeOnMessageCallback = void (optional any message, BrowserExtRuntimeMessageSender sender, BrowserExtRuntimeSendResponseCallback callback);
[NoInterfaceObject]
interface BrowserExtBrowserRuntime {
    object getManifest();
    DOMString getURL(DOMString path);
    attribute DOMString id;
    void onConnect(BrowserExtRuntimeOnConnectCallback callback);
    void onInstalled(BrowserExtRuntimeOnInstalledCallback callback);
    void onMessage(BrowserExtRuntimeOnMessageCallback callback);
    Promise<any> sendMessage(optional DOMString extensionId, any message);
    attribute BrowserExtRuntimePort Port;
    attribute BrowserExtRuntimeMessageSender MessageSender;
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExt"]
interface BrowserExtRuntimeAPI {
    readonly attribute BrowserExtRuntime runtime; 
};
Browser implements BrowserExtRuntimeAPI;

tabs

browser.tabs给出了标签页的API:

enum BrowserExtTabMutedReasonDetails { "user", "capture", "extension" };
enum BrowserExtRunAt { "document_end", "document_idle", "document_start" };
enum BrowserExtTabStatus { "complete", "loading" };
enum BrowserExtWindowTypes { "app", "normal", "panel", "popup" };
enum BrowserExtTabsCaptureVisibleTabFormat { "jpeg", "png" };
dictionary BrowserExtTabsTab {
    boolean active;
    boolean audible;
    DOMString? favIconUrl;
    boolean highlighted;
    long height;
    long id;
    boolean incognito;
    long index;
    TabMutedDetails? mutedDetails;
    long openerTabId;
    boolean pinned;
    DOMString? sessionId;
    DOMString? status;
    DOMString? title;
    DOMString? url;
    long width;
    long windowId;
};
dictionary BrowserExtTabMutedDetails {
    DOMString? extensionId;
    boolean muted;
    TabMutedReasonDetails? reason;
};
dictionary BrowserExtTabConnectDetails {
    long frameId;
    DOMString? name;
};
dictionary BrowserExtTabCreateDetails {
    boolean active;
    long index;
    long openerTabId;
    boolean pinned;
    DOMString? url;
    long windowId;
};
dictionary BrowserExtTabScriptAndCSSDetails {
    boolean allFrames;
    DOMString? code;
    DOMString? file;
    long frameId;
    boolean matchAboutBlank;
    BrowserExtRunAt? runAt;
};
dictionary BrowserExtTabsCaptureVisibleTabDetails {
    BrowserExtTabsCaptureVisibleTabFormat imageCaptureFormat;
    long jpegQuality;
};
dictionary BrowserExtTabQueryDetails {
    boolean active;
    boolean audible;  
    boolean currentWindow;
    boolean highlighted;
    long index;
    boolean lastFocusedWindow;
    boolean muted;
    boolean pinned;
    TabStatus? status;
    DOMString? title;
    (DOMString? or sequence<DOMString>?) url;
    long windowId;
    WindowType? windowType;
};
dictionary BrowserExtTabReloadDetails {
    boolean bypassCache;
};
dictionary BrowserExtTabSendMessageDetails {
    long frameId;
};
dictionary BrowserExtTabUpdateDetails {
    boolean active;
    boolean highlighted;
    boolean muted;
    long openerTabId;
    boolean pinned;
    DOMString? url;
};
dictionary BrowserExtTabIdWindowId {
    long tabId;
    long windowId;
};
dictionary BrowserExtTabsWindowIdIsWindowClosing {
    boolean isWindowClosing;
    long windowId;
};
dictionary BrowserExtTabsOnUpdatedChangeDetails {
    boolean audible;    
    DOMString? favIconUrl;
    TabMutedDetails? mutedDetails;
    boolean pinned;
    DOMString? status;
    DOMString? title;
    DOMString? url;
};
callback BrowserExtTabsOnActivatedCallback = void (BrowserExtTabIdWindowId activeDetails);
callback BrowserExtTabsOnCreatedCallback = void (BrowserExtTabTab tab);
callback BrowserExtTabsOnRemovedCallback = void (long tabId, BrowserExtTabsWindowIdIsWindowClosing removeDetails);
callback BrowserExtTabsOnUpdatedCallback = void (long tabId, BrowserExtTabsOnUpdatedChangeDetails details, BrowserExtTabsTab tab);
[NoInterfaceObject]
interface BrowserExtBrowserTabs {
    Promise<DOMString> captureVisibleTab(long windowId, BrowserExtTabsCaptureVisibleTabDetails details);
    RuntimePort connect(long tabId, BrowserExtTabConnectDetails details);
    Promise<BrowserExtTabsTab> create(BrowserExtTabCreateDetails details);
    void executeScript(long tabId, BrowserExtTabScriptAndCSSDetails details);
    Promise<BrowserExtTabsTab> get(long tabId);
    Promise<BrowserExtTabsTab> getCurrent();
    void insertCSS(long tabId, BrowserExtTabScriptAndCSSDetails details);
    void onActivated(BrowserExtTabsOnActivatedCallback callback);
    void onCreated(BrowserExtTabsOnCreatedCallback callback);
    void onRemoved(BrowserExtTabsOnRemovedCallback callback);
    void onUpdated(BrowserExtTabsOnUpdatedCallback callback);
    Promise<BrowserExtTabsTab> query(BrowserExtTabQueryDetails queryDetails);
    Promise<void> reload(BrowserExtTabReloadDetails details);
    Promise<void> remove((long or sequence<long>) tabIds);
    Promise<any> sendMessage(long tabId, any message, optional BrowserExtTabSendMessageOptions details);
    Promise<BrowserExtTabsTab> update(optional long tabId, BrowserExtTabUpdateDetails details);
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtTabs"]
interface BrowserExtTabsAPI {
readonly attribute BrowserExtTabs tabs; 
};
Browser implements BrowserExtTabsAPI;

webNavigation

browser.webNavigation给出了导航的API:

enum BrowserExtTransitionType { "link", "typed" };
dictionary BrowserExtWebNavigationOnBeforeNavigateDetails {
    long frameId;
    long parentFrameId;
    long tabId;
    double timeStamp;
    DOMString url;
};
dictionary BrowserExtWebNavigationOnCommittedDetails {
    long frameId;
    long processId;
    long tabId;
    double timeStamp;
    TransitionType transitionType;
    DOMString url;
};
dictionary BrowserExtWebNavigationOnCompletedDetails {
    long frameId;
    long processId;
    long tabId;
    double timeStamp;
    DOMString url;
};
dictionary BrowserExtWebNavigationOnDOMContentLoadedDetails {
    long frameId;
    long processId;
    long tabId;
    double timeStamp;
    DOMString url;
};
dictionary BrowserExtWebNavigationOnErrorOccurredDetails {
    DOMString error;
    long frameId;
    long tabId;
    double timeStamp;
    DOMString url;
};
dictionary BrowserExtWebNavigationOnReferenceFragmentUpdatedDetails {
    long frameId;
    long processId;
    long tabId;
    double timeStamp;                           
    BrowserExtTransitionType transitionType;
    DOMString url;
};
callback BrowserExtWebNavigationOnBeforeNavigateCallback = void (BrowserExtWebNavigationOnBeforeNavigateDetails details);
callback BrowserExtWebNavigationOnCommittedCallback = void (BrowserExtWebNavigationOnCommittedDetails details);
callback BrowserExtWebNavigationOnCompletedCallback = void (BrowserExtWebNavigationOnCompletedDetails details);
callback BrowserExtWebNavigationOnDOMContentLoadedCallback = void (BrowserExtWebNavigationOnDOMContentLoadedDetails details);
callback BrowserExtWebNavigationOnErrorOccurredCallback = void (BrowserExtWebNavigationOnErrorOccurredDetails details);
callback BrowserExtWebNavigationOnReferenceFragmentUpdated = void (BrowserExtWebNavigationOnReferenceFragmentUpdatedDetails details);
[NoInterfaceObject]
interface BrowserExtBrowserWebNavigation {
    void onBeforeNavigate(BrowserExtWebNavigationOnBeforeNavigateCallback callback);
    void onCommitted(BrowserExtWebNavigationOnCommittedCallback callback);
    void onCompleted(BrowserExtWebNavigationOnCompletedCallback callback);
    void onDOMContentLoaded(BrowserExtWebNavigationOnDOMContentLoadedCallback callback);
    void onErrorOccurred(BrowserExtWebNavigationOnErrorOccurredCallback callback);
    void onReferenceFragmentUpdated(BrowserExtWebNavigationOnReferenceFragmentUpdated callback);
};
    
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtWebNavigation"]
interface BrowserExtWebNavigationAPI {
    readonly attribute BrowserExtWebNavigation webNavigation; 
};
Browser implements BrowserExtWebNavigationAPI;

webRequest

browser.webRequest给出了web请求的API:

enum BrowserExtResourceType { "font", "image", "main_frame", "object", "other", "ping", "script", "stylesheet", "sub_frame", "xmlhttprequest" };
dictionary BrowserExtWebRequestUploadDetails {
    any bytes;
    DOMString? file;
};
dictionary BrowserExtWebRequestRequestBody {
    DOMString? error;
    object? formData;
    sequence<BrowserExtWebRequestUploadData>? rawData;
};
dictionary BrowserExtWebRequestHttpHeader {
    DOMString keyName;
    any value;
};
dictionary BrowserExtWebRequestHttpHeaders {
    sequence<BrowserExtWebRequestHttpHeader> data; 
};
dictionary BrowserExtWebRequestOnBeforeRequestDetails {
    long frameId;
    DOMString method;
    long parentFrameId;
    BrowserExtWebRequestRequestBody? requestBody;
    DOMString requestId;
    long tabId;
    double timeStamp;
    BrowserExtResourceType type;
    DOMString url;
};
dictionary BrowserExtWebRequestOnBeforeSendHeadersDetails {
    long frameId;
    DOMString method;
    long parentFrameId;
    BrowserExtWebRequestHttpHeaders? requestHeaders;
    DOMString requestId;
    long tabId;
    double timeStamp;
    BrowserExtResourceType type;
    DOMString url;
};
dictionary BrowserExtWebRequestOnCompletedDetails {
    long frameId;
    boolean fromCache;
    DOMString method;
    long parentFrameId;
    DOMString requestId;
    BrowserExtWebRequestHttpHeaders? responseHeaders;
    DOMString? serverIP;
    long statusCode;
    DOMString statusLine;
    long tabId;
    double timeStamp;   
    BrowserExtResourceType type;
    DOMString url;
}; 
dictionary BrowserExtWebRequestOnHeadersReceivedDetails {
    long frameId;
    DOMString method;
    long parentFrameId;
    DOMString requestId;
    BrowserExtWebRequestHttpHeaders? responseHeaders;
    long statusCode;
    DOMString statusLine;
    long tabId;
    double timeStamp;   
    BrowserExtResourceType type;
    DOMString url;
};
dictionary BrowserExtWebRequestOnSendHeadersDetails {
    long frameId;
    DOMString method;
    long parentFrameId;
    BrowserExtWebRequestHttpHeaders? requestHeaders;
    DOMString requestId;
    long tabId;
    double timeStamp;   
    BrowserExtResourceType type;
    DOMString url;
};
callback BrowserExtWebRequestOnBeforeRequestCallback = void (BrowserExtWebRequestOnBeforeRequestDetails details);
callback BrowserExtWebRequestOnBeforeSendHeadersCallback = void (BrowserExtWebRequestOnBeforeSendHeadersDetails details);
callback BrowserExtWebRequestOnCompletedCallback = void (BrowserExtWebRequestOnCompletedDetails details);
callback BrowserExtWebRequestOnHeadersReceivedCallback = void (BrowserExtWebRequestOnHeadersReceivedDetails details);
callback BrowserExtWebRequestOnSendHeadersCallback = void (BrowserExtWebRequestOnSendHeadersDetails details);
[NoInterfaceObject]
interface BrowserExtBrowserWebRequest {
    void onBeforeRequest(BrowserExtWebRequestOnBeforeRequestCallback callback);
    void onBeforeSendHeaders(BrowserExtWebRequestOnBeforeSendHeadersCallback callback);
    void onCompleted(BrowserExtWebRequestOnCompletedCallback callback);
    void onHeadersReceived(BrowserExtWebRequestOnHeadersReceivedCallback callback);
    void onSendHeaders(BrowserExtWebRequestOnSendHeadersCallback callback);
};
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExtWebRequest"]
interface BrowserExtWebRequestAPI {
    readonly attribute BrowserExtWebRequest webRequest; 
};
Browser implements BrowserWebRequestAPI;

windows

browser.windows给出了浏览器窗口的API:

enum BrowserExtWindowsWindowType { "detached_panel", "normal", "panel", "popup" };
enum BrowserExtWindowsWindowState { "docked", "fullscreen", "maximized", "minimized", "normal" };
dictionary BrowserExtCreateWindowDetails {
    boolean focused;
    long height;
    boolean incognito;
    long left;
    BrowserExtWindowsWindowState? state;
    long tabId;
    long top;
    (DOMString? or sequence<DOMString>?) url;
    long width;
    BrowserExtWindowsWindowType? windowType;
};
dictionary BrowserExtGetWindowDetails {
    boolean populate;
    sequence<BrowserExtWindowsWindowType>? windowTypes;
};
dictionary BrowserExtWindowUpdateDetails {
    boolean drawAttention;
    boolean focused;
    long height;
    long left;
    long top;
    long width;
    BrowserExtWindowState? windowState;
};
dictionary BrowserExtWindowsWindow {
    boolean alwaysOnTop;
    boolean focused;
    long height;
    long id;
    boolean incognito;
    long left;
    sequence<BrowserExtTabsTab>? tabs;
    long top;
    DOMString? sessionId;
    BrowserExtWindowsWindowState? state;
    long width;
    BrowserExtWindowsWindowType? windowType;
};
callback BrowserExtWindowsOnFocusChangedCallback = void (long windowId);
[NoInterfaceObject]
interface BrowserExtWindows {
    Promise<BrowserExtWindowsWindow> create(CreateWindowDetails details);
    Promise<BrowserExtWindowsWindow> get(long windowId, optional BrowserExtGetWindowDetails details);
    Promise<sequence<BrowserExtWindowsWindow>> getAll(optional BrowserExtGetWindowDetail details);
    Promise<BrowserExtWindowsWindow> getCurrent(optional BrowserExtGetWindowDetail details);
    Promise<BrowserExtWindowsWindow> getLastFocused(optional BrowserExtGetWindowDetail details);
    void onFocusChanged(BrowserExtWindowsOnFocusChangedCallback callback);
    Promise<BrowserExtWindowsWindow> update(long windowId, optional BrowserExtWindowUpdateDetails details);
};
    
[NoInterfaceObject, Exposed=Window, CheckAnyPermissions="browserExt"]
interface BrowserExtWindowsAPI {
readonly attribute BrowserExtWindows windows; 
};
Browser implements BrowserExtWindowsAPI;

更多信息

各浏览器还支持大量其它API在这里未能尽录,请参考:

关键词 web