一、什么是Extension

扩展是自定义浏览体验的小型软件,它可以让用户通过多种方式定制Chrome浏览器的功能和行为。

二、Extension是怎么运行的

  • 扩展使用web技术构建,包括HTML,JavaScript和CSS。

  • 扩展运行在一个单独的沙盒执行环境中,并与Chrome浏览器交互。

  • 扩展允许使用Chrome提供的API来修改浏览器的行为,也可以访问Web内容来扩展浏览器。

  • 扩展API允许扩展的代码访问浏览器的功能,例如激活标签页、修改网络请求,等。

三、Chrome扩展商店的政策

  • 一个扩展必须满足一个定义精确的单一目的。单个扩展可以包含多个组件和一系列功能,只要一切都有助于实现一个共同目的。

  • 用户界面应该是最小化的,有目的的。

四、官方文档

https://developer.chrome.com/docs/extensions/mv3/getstarted/

官方文档比较清楚,具备简单的英文基础就能阅读。

在Chrome88后,Chrome开始支持Manifest V3,扩展商店在2021年1月开始接受MV3扩展。

五、一个Extension的基本组成

  • manifest.json:每个扩展都包含一个JSON格式的manifest文件,提供组件的重要信息,例如最重要的文件和扩展可能使用的功能。

  • 图标:每一个扩展都包含一个图标,显示在浏览器工具栏。工具栏图标更易于访问和提醒用户安装了哪些扩展。大多数时候,用户通过点击图标弹出的窗口与扩展交互。

  • Background Script:后台脚本是扩展的事件处理程序,包含对扩展重要浏览器事件的监听器。它通常处于休眠状态,直到触发事件,然后执行指示的逻辑。高效的后台脚本仅在需要时加载,并在空闲时卸载。

  • UI Elements:扩展的用户界面应该是目的明确且最小化的设计。应该在不分散注意力的情况下扩展和增强浏览体验。大多数扩展包括browser action或page action,也可以包含其他形式UI,例如context menus,多功能框(omnibox),快捷键。

  • Content scripts:扩展程序利用content script向web page中做读取和写入操作。content script在浏览器加载的网页中执行。content script可以通过message 交换与其所属的extension交流,还可以利用storage API储存信息。

  • Options page:就像浏览器允许用户定制extension一样,options page可以用来定制extension。Options page可以根据用户需求来启用和关闭功能。

六、使用Chrome API

除了可以使用网页所使用的API,extension还可以使用浏览器特殊提供的API。例如,extension和网页中的代码都可以访问标准APIwindow.open()方法打开一个URL,但是extension还可以使用Chrome提供的tabs.create方法来指定哪个tab打开URL。

七、异步(asynchronous)方法和同步(synchronous)方法

大多数Chrome API方法都是异步的,他们会在操作执行完毕之前就return。如果一个一个异步操作需要用到操作结果,可以向这个方法传递一个回调函数(callback function)。在方法return以后,过些时候,有时会久一点,回调函数才会被执行。

例如,当extension需要导航当前tab到一个新URL,需要获得当前tab的ID,然后更新tab的地址到新的URL。

如果tab.query方法是同步方法,代码可能如下。

1
2
3
4
//THIS CODE DOESN'T WORK
var tab = chrome.tabs.query({'active': true}); //WRONG!!!
chrome.tabs.update(tab.id, {url:newUrl});
someOtherFunction();

以上代码会执行失败,因为query()是一个异步方法。会在query操作执行完之前就return,此时的return没有返回需要的值。

当一个方法的签名(signature)中包含一个callback参数,那这是个异步方法。

1
2
// query()就是一个异步方法
chrome.tabs.query(object queryInfo, function callback)

正确使用query的代码如下。

1
2
3
4
5
6
//以下代码的正确执行顺序,根据行号是:1,4,2
//虽然update()方法也是异步方法,但因为不需要使用update的执行结果,所以不需要添加callback参数。
chrome.tabs.query({'active': true}, function(tabs) {
  chrome.tabs.update(tabs[0].id, {url: newUrl});
});
someOtherFunction();

chrome提供的API中也包含同步方法,如获取URL的方法,会立刻返回一个string。

1
2
// Synchronous methods have no callback option and returns a type of string
string chrome.runtime.getURL()

更多API

可以查看官方API文档获取更多API细节。

八、Extenion不同page之间的通信

一个扩展的不同组件(component)之间经常需要通信,不同的HTML page可以使用chrome.extension提供的几个方法,找到其他page,例如,getViews()和getBackgroundPage()。一旦一个page拥有同一个extension之下的其他page的引用(reference),就可以调用被引用的page中的函数以及操作它的DOM。

除此之外,同一个extension包含的组件,都可以访问使用storage API存储的信息,也可以通过message passing来通信。

九、保存数据和隐身模式

Extension可以使用storage API,HTML5标准web storage API,或者发送服务器请求来达到保存数据的目的。当extension需要保存数据时,首先要考虑是否是隐身模式窗口,默认情况下,扩展不在隐身模式运行。

隐身模式承诺当下窗口中的浏览不会留下痕迹(no tracks),所以,在处理来自隐身窗口的数据时,扩展程序应该兑现这一承诺。

如果扩展程序通常会保存浏览历史记录,请不要在隐身窗口保存。但是,扩展程序可以存储来自任何窗口的设置首选项,无论是否隐身。

要检测窗口是否处于隐身模式,请检查相关tabs.Tab 或 windows.Window 对象的隐身属性。

1
2
3
4
5
6
7
function saveTabData(tab) {
  if (tab.incognito) {
    return;
  } else {
    chrome.storage.local.set({data: tab.url});
  }
}