chrome扩展开发
Chrome浏览器在全球都拥有可观的忠实用户,抛去其占据了浏览器市场的霸主地位不说,其具备了众多的优点,如良好的用户体验,简单的开发规范等等。
归纳为以下几点:
- 市场占有率高,用户基础庞大;
- 开发流程简单,方便快速上手;
- 应用场景广泛,兼容webkit内核(360极速浏览器、360安全浏览器、搜狗浏览器、QQ浏览器等等);
- 可扩展性强,非weikit内核的浏览器也有一定的支持(如Firefox)
初试插件
- 首先创建一个文件夹,用于存储插件相关资源文件
- 创建对应需要的目录和manifest.json
manifest.json文件配置
这是一个简单的配置,并非完整配置,特别注意下,manifest.json文件中不能包含注释!否则浏览器无法正常解析。
{
// 必须的字段
// 清单文件的版本,这个必须写,而且必须是2
"manifest_version": 2,
// 插件的名称
"name": "SN-七七",
"version": "1.0",
// 建议提供的字段
// 插件描述
"description": "这是chrome插件的描述信息",
// 图标,一般偷懒全部用一个尺寸的也没问题
"icons":
{
"16": "img/icon.png",
"48": "img/icon.png",
"128": "img/icon.png"
},
// 多选一,或者都不提供
// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
"browser_action": {
"default_icon": "img/icon.png",
// 图标悬停时的标题,提示信息
"default_title": "这是一个示例Chrome插件",
"default_popup": "popup.html"
},
// 根据需要提供
// 权限申请
"permissions": [
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"https://www.baidu.com/",//可以通过executeScript或者insertCSS访问的网站
]
}
配置完成后,打开chrome浏览器,选择【管理扩展插件】,打开开发者模式,点击【加载已解压的扩展程序】,选择刚刚创建的目录,即可看到插件加载成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W1iYX2Y5-1608169290780)(https://s1.ax1x.com/2020/11/04/B6v2a8.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0FlNkMvs-1608169290783)(https://s1.ax1x.com/2020/11/04/B6xqOI.png)]
浏览器右上角也会显示插件的图标。
在开发应用(扩展)时,需要把这些文件都放到同一个目录下。发布应用(扩展)时,这个目录全部打包到一个应用(扩展)名是
.crx
的压缩文件中。如果使用谷歌浏览器应用开放平台或Chrome Developer Dashboard上传应用(扩展),可以自动生成.crx
文件。
接下来看一下完整配置
manifest.json
{
// 必须的字段
// 清单文件的版本,这个必须写,而且必须是2
"manifest_version": 2,
// 插件的名称
"name": "SN-schcb",
"version": "1.0",
// 建议提供的字段
// 插件描述
"description": "这是chrome插件的描述信息",
// 图标,一般偷懒全部用一个尺寸的也没问题
"icons":
{
"16": "img/icon.png",
"48": "img/icon.png",
"128": "img/icon.png"
},
// 多选一,或者都不提供
// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
"browser_action": {
"default_icon": "img/icon.png",
// 图标悬停时的标题,提示信息
"default_title": "这是一个示例Chrome插件",
"default_popup": "popup.html"
},
// 根据需要提供
// 权限申请
"permissions": [
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"https://www.baidu.com/",//可以通过executeScript或者insertCSS访问的网站
],
// 会一直常驻的后台JS或后台页面
"background":
{
// 2种指定方式,如果指定JS,那么会自动生成一个背景页
//"scripts": ["js/background.js"]
"page": "background.html"
},// 需要直接注入页面的JS
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],
// "<all_urls>" 表示匹配所有地址
"matches": ["<all_urls>"],
// 多个JS按顺序注入
"js": ["js/jquery-1.8.3.js", "js/content-script.js"],
// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
"css": ["css/custom.css"],
// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
"run_at": "document_start"
},
// 这里仅仅是为了演示content-script可以配置多个规则
{
"matches": ["*://*/*.png", "*://*/*.jpg", "*://*/*.gif", "*://*/*.bmp"],
"js": ["js/show-image-content-size.js"]
}
],
// 权限申请
"permissions":
[
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"http://*/*", // 可以通过executeScript或者insertCSS访问的网站
"https://*/*" // 可以通过executeScript或者insertCSS访问的网站
],
// 普通页面能够直接访问的插件资源列表,如果不设置是无法直接访问的
"web_accessible_resources": ["js/inject.js"],
// 插件主页,这个很重要,不要浪费了这个免费广告位
"homepage_url": "https://www.baidu.com",
// 覆盖浏览器默认页面
"chrome_url_overrides":
{
// 覆盖浏览器默认的新标签页
"newtab": "newtab.html"
},
// Chrome40以前的插件配置页写法
"options_page": "options.html",
// Chrome40以后的插件配置页写法,如果2个都写,新版Chrome只认后面这一个
"options_ui":
{
"page": "options.html",
// 添加一些默认的样式,推荐使用
"chrome_style": true
},
// 向地址栏注册一个关键字以提供搜索建议,只能设置一个关键字
"omnibox": { "keyword" : "go" },
// 默认语言
"default_locale": "zh_CN",
// devtools页面入口,注意只能指向一个HTML文件,不能是JS文件
"devtools_page": "devtools.html"
}
参数-browser_action
browser_action 指定扩展的图标放在 Chrome 工具栏中,它定义了扩展图标文件位置(default_icon)、悬浮提示(default_title)和点击扩展图标所显示的页面位置(default_popup)。
// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
"browser_action": {
"default_icon": "img/icon.png",
// 图标悬停时的标题,提示信息
"default_title": "你好,我是暴躁的小七七,你可不要碰我啊!",
"default_popup": "popup.html"
},
展示效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcsZemGH-1608169290787)(https://s1.ax1x.com/2020/11/04/BgGRpT.png)]
popup.html就是单纯的html文件,点击小图标即可看到popup中的内容
参数-background
background 可以使扩展常驻后台,比较常用的是指定子属性 scripts,表示在扩展启动时自动创建一个包含所有指定脚本的页面。
// 会一直常驻的后台JS或后台页面
"background":
{
// 2种指定方式,如果指定JS,那么会自动生成一个背景页
//"scripts": ["js/background.js"]
"page": "background.html"
},
参数-chrome_url_overrides
可以自定义的页面替换 Chrome 相应默认的页面,比如新标签页(newtab)、书签页面(bookmarks)和历史记录(history)。
// 覆盖浏览器默认页面
"chrome_url_overrides":
{
// 覆盖浏览器默认的新标签页
"newtab": "newtab.html"
},
参数-content-scripts
所谓content-scripts,其实就是Chrome插件中向页面注入脚本的一种形式(虽然名为script,其实还可以包括css的),借助content-scripts
我们可以实现通过配置的方式轻松向指定页面注入JS和CSS(如果需要动态注入,可以参考下文),最常见的比如:广告屏蔽、页面CSS定制,等等。
{
// 需要直接注入页面的JS
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],
// "<all_urls>" 表示匹配所有地址
"matches": ["<all_urls>"],
// 多个JS按顺序注入
"js": ["js/jquery-1.8.3.js", "js/content-script.js"],
// JS的注入可以随便一点,但是CSS的注意就要千万小心了,因为一不小心就可能影响全局样式
"css": ["css/custom.css"],
// 代码注入的时间,可选值: "document_start", "document_end", or "document_idle",最后一个表示页面空闲时,默认document_idle
"run_at": "document_start"
}
],
}
特别注意,如果没有主动指定run_at
为document_start
(默认为document_idle
),下面这种代码是不会生效的:
document.addEventListener('DOMContentLoaded', function()
{
console.log('我被执行了!');
});
content-scripts
和原始页面共享DOM,但是不共享JS,如要访问页面JS(例如某个JS变量),只能通过injected js
来实现。
参数-homepage_url
// 插件主页,这个很重要,不要浪费了这个免费广告位
"homepage_url": "https://www.baidu.com",
参数-options_page
定义了扩展的设置页面,配置后在扩展图标点击右键可以看到 选项,点击即打开指定页面
// Chrome40以后的插件配置页写法
"options_ui":
{
"page": "options.html",
// 添加一些默认的样式,推荐使用
"chrome_style": true
},
参数-permissions
属性是一个数组,它定义了扩展需要向 Chrome 申请的权限,比如通过 XMLHttpRequest 跨域请求数据、访问浏览器选项卡(tabs)、获取当前活动选项卡(activeTab)、浏览器通知(notifications)、存储(storage)等,可以根据需要添加。。
// 权限申请
"permissions": [
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"https://www.baidu.com/",//可以通过executeScript或者insertCSS访问的网站
],
功能形式
右键菜单
通过开发Chrome插件可以自定义浏览器的右键菜单,主要是通过chrome.contextMenus
API实现,右键菜单可以出现在不同的上下文,比如普通页面、选中的文字、图片、链接,等等,如果有同一个插件里面定义了多个菜单,Chrome会自动组合放到以插件名字命名的二级菜单里,如下:
background.js文件:
chrome.contextMenus.create({
type: 'normal', // 类型,可选:["normal", "checkbox", "radio", "separator"],默认 normal
title: '菜单的名字', // 显示的文字,除非为“separator”类型否则此参数必需,如果类型为“selection”,可以使用%s显示选定的文本
contexts: ['page'], // 上下文环境,可选:["all", "page", "frame", "selection", "link", "editable", "image", "video", "audio"],默认page
onclick: function(){}, // 单击时触发的方法
parentId: 1, // 右键菜单项的父菜单项ID。指定父菜单项将会使此菜单项成为父菜单项的子菜单
documentUrlPatterns: 'https://*.baidu.com/*' // 只在某些页面显示此右键菜单
});
// 删除某一个菜单项
chrome.contextMenus.remove(menuItemId);
// 删除所有自定义右键菜单
chrome.contextMenus.removeAll();
// 更新某一个菜单项
chrome.contextMenus.update(menuItemId, updateProperties);
- 定义多个菜单形式
chrome.contextMenus.create({
title: '父菜单1', // %s表示选中的文字
id: '0',
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
});
chrome.contextMenus.create({
title: '父菜单2', // %s表示选中的文字
id: '1',
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
});
chrome.contextMenus.create({
title: '子菜单1:%s', // %s表示选中的文字
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
parentId: '0',
onclick: function(params)
{
// 注意不能使用location.href,因为location是属于background的window对象
chrome.tabs.create({url: `https://www.baidu.com/s?wd=${encodeURI(params.selectionText)}&ie=UTF-8`});
}
});
chrome.contextMenus.create({
title: '子菜单2:%s', // %s表示选中的文字
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
parentId: '0',
onclick: function(params)
{
// 注意不能使用location.href,因为location是属于background的window对象
chrome.tabs.create({url: `https://www.baidu.com/s?wd=${encodeURI(params.selectionText)}&ie=UTF-8`});
}
});
chrome.contextMenus.create({
title: '子菜单1:%s', // %s表示选中的文字
contexts: ['selection'], // 只有当选中文字时才会出现此右键菜单
parentId: '1',
onclick: function(params)
{
// 注意不能使用location.href,因为location是属于background的window对象
chrome.tabs.create({url: `https://www.baidu.com/s?wd=${encodeURI(params.selectionText)}&ie=UTF-8`});
}
});
效果如下: