Chrome 插件是什么
其实,这东西应该叫Chrome扩展(Chrome Extension),Chrome插件这种叫法是大众的习惯称呼。
Chrome 插件 目录结构
├── manifest.json
├── html
│ └── index.html
├── images
│ ├── icon-128.png
│ └── icon-16.png
├── scripts
│ └── background.js
├── styles
│ └── main.css
└─_locales
├── en
│ └── messages.json
│
└── zh_CN
└── messages.json
上图可以看出,Chrome 插件 其实就是一个由HTML、CSS、JS、图片等资源组成的一个应用,本质上来说就是webapp。
Chrome 插件 能帮我们做什么?
- 网络请求拦截处理
- 书签控制
- 窗口控制
- 通信机制
- 右键菜单控制
- 搜索栏快捷操作
- ...
文件介绍
manifest.json
{
// 清单文件的版本,这个必须写,而且必须是2
"manifest_version": 2,
// 插件的名称
"name": "demo",
// 插件的版本
"version": "1.0.0",
// 插件描述
"description": "简单的Chrome扩展demo",
// 图标,一般偷懒全部用一个尺寸的也没问题
"icons":
{
"16": "img/icon.png",
"48": "img/icon.png",
"128": "img/icon.png"
},
// 会一直常驻的后台JS或后台页面
"background":
{
// 2种指定方式,如果指定JS,那么会自动生成一个背景页
"page": "background.html"
//"scripts": ["js/background.js"]
},
// 浏览器右上角图标设置,browser_action、page_action、app必须三选一
"browser_action":
{
"default_icon": "img/icon.png",
// 图标悬停时的标题,可选
"default_title": "这是一个示例Chrome插件",
"default_popup": "popup.html"
},
// 需要直接注入页面的JS
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],
// "" 表示匹配所有地址
"matches": [""],
// 多个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"
},
],
// 权限申请
"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"
}
content-scripts
Content scripts是在Web页面内运行的javascript脚本。通过使用标准的DOM,它们可以获取浏览器所访问页面的详细信息,并可以修改这些信息。我们可以使用它来进行广告屏蔽、页面图片提取视频提取等。
配置如下:
{
// 需要直接注入页面的JS
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],
// "" 表示匹配所有地址
"matches": [""],
// 多个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-scripts和原始页面共享DOM,但是不共享JS,如要访问页面JS(例如某个JS变量),只能通过injected js来实现。
不能使用除了chrome.extension之外的chrome.* 的接口。
不过Content scripts 可以使用messages机制与它所在的扩展通信,来间接使用chrome.*接口,或访问扩展数据。Content scripts还可以通过共享的DOM来与web页面通信。
background
background后台页面,在浏览器前台看不到的页面,可以以后台进程的方式进行运行,也可以以事件的方式运行。需要打开扩展程序的开发者模式才能看到。
打开方式如下:
配置如下:
{
// 会一直常驻的后台JS或后台页面
"background":
{
// 2种指定方式,如果指定JS,那么会自动生成一个背景页
"page": "background.html"
//"scripts": ["js/background.js"]
},
}
所有页面共用同一个background,它与外部通过消息传递。 它的权限非常高,可以无限制跨域,也可以通过chrome.storage持久化去保存一些用户配置。
popup
popup是点击browser_action
或者page_action
图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。popup的控制台是直接右键popup,选择检查即可。
popup可以写你想要的HTML内容,不过它的生命周期很短,单击图标打开popup,焦点离开又立即关闭。
在权限上,它和background非常类似,它们之间最大的不同是生命周期的不同,popup中可以直接通过chrome.extension.getBackgroundPage()获取background的window对象。
功能展示
右键菜单
Chrome插件可以对普通页面、选中的文字、图片、链接等元素,在右键的时候,是通过chrome.contextMenusAPI
实现一些快捷功能。
右键菜单示例
// manifest.json
{"permissions": ["contextMenus"]}
// background.js
chrome.contextMenus.create({
title: "右键菜单",
onclick: function(){alert('您点击了右键菜单!');}
});
效果:
chrome_url_overrides
配置chrome_url_overrides
可以替换Chrome特定页面。
配置如下:
"chrome_url_overrides": {
"newtab": "newtab.html", // 替换鑫打开标签 chrome://newtab
"history": "history.html", // 替换历史记录 chrome://history
"bookmarks": "bookmarks.html" // 替换浏览器书签 chrome://bookmarks
}
注意:
- 一个扩展只能替代一个特定页面;
- 不能替代隐身窗口的新标签页;
- 网页必须设置title,以便隐藏网页的URL。
popup动态注入或执行JS
background和popup中无法直接访问页面DOM,但是可以通过chrome.tabs.executeScript来执行脚本,从而实现访问web页面的DOM。
manifest.json
配置:
{
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
}
localStorage中插值
// 获取当前选项卡ID
function getCurrentTabId(callback) {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
if (callback) callback(tabs.length ? tabs[0].id : null);
});
}
function executeScriptToCurrentTab(code) {
getCurrentTabId((tabId) => {
chrome.tabs.executeScript(tabId, { code });
});
}
executeScriptToCurrentTab(`localStorage.setItem('overviewGuideShow', false)`);
消息通信
概览
content-script | popup-js | background-js | |
---|---|---|---|
content-script | - | chrome.runtime.sendMessage chrome.runtime.connect |
chrome.runtime.sendMessage chrome.runtime.connect |
popup-js | chrome.tabs.sendMessage chrome.tabs.connect |
- | chrome.extension.getBackgroundPage() |
background-js | chrome.tabs.sendMessage chrome.tabs.connect |
chrome.extension.getViews | - |
popup和background
popup可以直接调用background中的JS方法,也可以直接访问background的DOM:
// background.js
function test() {
alert('我是background!');
}
// popup.js
var background = chrome.extension.getBackgroundPage();
background.test();
alert(bg.document.body.innerHTML); // 获取background的DOM
popup、background向content主动发消息
background.js
或者popup.js
:
function sendMessageToContentScript(message, callback) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, message, function(response) {
if(callback) callback(response);
});
});
}
sendMessageToContentScript({text: '我是popup'}, function(response) {
console.log('来自content的回复:'+response);
});
content-script.js
:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log(request);
sendResponse('收到消息popup或background的消息');
});
content-script主动发消息给后台
content-script.js
:
chrome.runtime.sendMessage({greeting: '我是content-script,这是我发送的消息!'}, (response) => {
console.log('这是后台返回的消息:' + response);
});
background.js
或者 popup.js
:
// 监听来自content-script的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log(request, sender, sendResponse);
sendResponse('我是后台,我已收到你的消息:' + JSON.stringify(request));
});
注意:
popup每次打开都会走一次创建渲染流程,所以在popup未打开的情况下是接收不到content_script发送的消息,只能通过background进行间接发送。
调试
打开扩展程序,勾选开发者模式
,选择加载已解压的扩展程序
。
同时在代码变动后都需要去刷新一下插件。
也可以用脚手架去开发Chrome插件,相对会更方便一些,脚手架可以帮我们热重载插件。
这里是一个Chrome 脚手架,使用 Vue.js + webpack 来开发和打包Chrome扩展, 支持热重载
https://github.com/jae-jae/chrome-extension-gulu