chrome-extension

本文将介绍一些chrome插件的基础内容,但是也省略了一些基础的内容。并不面向新手开发者。文中将会对content-js,inject-js,popup,background做一些粗略的介绍,尤其是对它们之间的通信方面。

核心介绍

manifest.json

首先是manifest.json,这是一个Chrome插件最重要也是必不可少的文件,用来配置所有和插件相关的配置,必须放在根目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
// 清单文件的版本,这个必须写,而且必须是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"
},

// content - js
"content_scripts":
[
{
//"matches": ["http://*/*", "https://*/*"],可以用正则匹配
// "<all_urls>" 表示匹配所有地址
"matches": ["<all_urls>"],
// 多个JS按顺序注入
"js": ["js/jquery-1.8.3.js", "js/content-script.js"],
// css
"css": ["css/custom.css"],
// 代码注入的时间,可选值:
//"document_start"页面记载前,
//"document_end"页面记载后,
//or "document_idle",最后一个表示页面空闲时,默认document_idle
"run_at": "document_start"
},
// 多个 content_javascripts规则
{
"matches": ["*://*/*.png"],
"js": ["js/show-image-content-size.js"]
}
],
// inject-js注入的需求配置
"web_accessible_resources": ["js/inject.js"],
// 权限申请
"permissions":
[
"contextMenus", // 右键菜单
"tabs", // 标签
"notifications", // 通知
"webRequest", // web请求
"webRequestBlocking",
"storage", // 插件本地存储
"http://*/*", // 跨域
"https://*/*" // 跨域
],
}

四个核心内容

本文给出的四个核心内容为:content-js,inject-js,popup,background。下面将会做一些个人的理解介绍。

popup是点击插件后,弹出来的小页面,当点击那个小按钮的时候,popup.html将会调用。同时包含在popup.html中的js文件也会被运行。popup.html无法直接写js脚本,必须通过包含的方式来写。

content-js

content-js是Chrome插件中向页面注入脚本的一种形式,会根据配置文件中指定的时间加载。

content_scripts中的脚本只是共享页面的DOM,而并不共享页面内嵌JavaScript的命名空间。也就是说,如果当前页面中的JavaScript有一个全局变量acontent_scripts中注入的脚本也可以有一个全局变量a,两者不会相互干扰。当然你也无法通过content_scripts访问到页面本身内嵌JavaScript的变量和函数。(http://www.ituring.com.cn/book/miniarticle/60212)

inject-js

inject-js与原生页面的js没有差别,因为inject-js就是将js代码注入到正在执行的Web页面中。它的实现方式是:先写一个js的文件,然后在content-js通过如下的类似代码,将写好的js文件注入到网页中。

1
2
3
4
5
6
//某个content-js页面
var s = document.createElement('script');
//提前写好的js脚本
s.src = chrome.extension.getURL('inject.js');
(document.head || document.body).appendChild(s);
# 同时你要注入的inject.js需要在manifest中的web_accessible_resources字段里进行声明,看上面的配置文件

关于上面提到的content-jsinject-js的区别和联系,inject-jscontent-js中进行注入。inject-js都可以获取web页面中的js的变量内容,而content-js不可以。

background

background是在页面打开后就一直运行的文件,可以理解为插件和页面的枢纽。

通信

关于这些组件的通信有四种:

  • content-jsinject-js的通信
  • backgroundcontent-js的通信
  • backgroundpopup.js的通信
  • popupcontent-js的通信

四种通信方式的整体思想一致。接收方使用监听函数,发送发使用发送函数

content-js 与 inject-js

demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//inject.js
f = document.getElementById('sb_form_go');
f.onclick = function(){

var message = document.getElementById('sb_form_q');
window.postMessage({'message':message.value}, '*');
return false;
}

//main.js

//注入js
function injectCustomJs(jsPath)
{
console.log('@@@@@@@@');
jsPath = jsPath || 'js/inject.js';
var temp = document.createElement('script');
temp.setAttribute('type', 'text/javascript');
// 获得的地址类似:chrome-extension://ihcokhadfjfchaeagdoclpnjdiokfakg/js/inject.js
temp.src = chrome.extension.getURL(jsPath);
// console.log(document)
document.body.append(temp);
}
console.log('11111111111111111111');

//接收消息
window.addEventListener("message", function(e)
{
console.log(e.data);
}, false);


injectCustomJs()

others

另外的三种通信模式如下:

同时在这三种接收方式中使用的监听函数相同

1
2
3
4
5
6
7
chrome.extension.onMessage.addListener(function(message,sender,callback){
//message为收到的消息
//sender是发送者的信息
//callback是回调函数,执行后会调用发送方的回调函数
console.log(message);
callback('执行成功');
});

然后就是发送函数,对于发送函数可以分为两种,一种是向插件中的组件发送内容,另一种是向web页面发送内容。向web页面发送内容,实质就是发送到content-js中。这两种发送的函数不同,分别为:chrome.runtime.sendMessag,chrome.tabs.sendMessage

1
2
3
4
5
6
7
8
9
10
11
chrome.tabs.query({active: true, currentWindow: true}, function(tabs)
{
chrome.tabs.sendMessage(tabs[0].id, message, function(response)
{
if(callback) callback(response);
});
});

chrome.runtime.sendMessage({greeting: '你好,我是content-script呀,我主动发消息给后台!'}, function(response) {
console.log('收到来自后台的回复:' + response);
});

下面给出一个demo