主要参考360的官方文档:
//http://open.chrome.360.cn/extension_dev/samples.html#a1f7cf79dd555b04fa8d603247a040e644996293
//http://open.chrome.360.cn/extension_dev/content_scripts.html
//http://open.chrome.360.cn/extension_dev/contentSecurityPolicy.html
代码主要工作流程如下:
(1) 用户点击插件按钮,后端js检测到点击事件,将前端js注入到当前页面中;
(2) 前端与后端通过端口建立长连接;
(3) 后端发送获取html的消息到前端,前端获取当前页面的html并发送回后端;
(4) 后端首先对html进行处理,获得其中要进行分析的部分,并把其发送到服务器端;
(5) 服务器端对数据进行分析处理,返回分析结果;
(6) 后端接收到分析结果后对数据进行处理返回到前端;
(7) 前端将结果显示在浏览器上。
还是不多解释,直接上代码:
manifest.json:
{
"name": "Entities analyzer",
"version": "1.0",
"manifest_version": 2,
"description": "Analyze the html page entities.",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": ["tabs", "<all_urls>"], //如果只是在某些情况下需要注入,可以使用permission字段,详见Programmatic injection。
"content_security_policy": "script-src 'self' http://127.0.0.1:8080/EL/ajaxSubmit.jsp; object-src 'self'",
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
background.js:
document.write("<script language=javascript src='jquery.min.js'></script>");
//监听通信接口
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "knockkno");
port.postMessage({type: "to-front", data: "document"});
port.onMessage.addListener(function(msg) {
if (msg.type == "to-front")
return;
document.body.innerHTML=""
document.write(msg.data);
data = $('p').not($('p a').parent());
var text = "";
for (var i=0; i<data.length; i++){
text += data[i].innerText;
text += ' ';
}
// alert(text);
var param = {};
param.submitData = text; //与服务器的交互
var label = true;
$.ajax({
type: "post",
url: "http://127.0.0.1:8080/EL/ajaxSubmit.jsp",
data: param,
// dataType:'jsonp',
error: function(request) {
alert("出错");
},
success: function(data) {
if (label == false)
return;
label = false;
// alert(data);
data = data.slice(6, -2);
data = data.split(", ");
change = $('p').not($('p a').parent());
$('p').not($('p a').parent()).each(function(){
if (checknum($(this).text()))
return;
for (var i=0; i<data.length; i++){
var a = data[i].substring(0, data[i].indexOf('='));
if ($(this).text().indexOf(a) != -1){
var b = data[i].substring(data[i].indexOf('=')+1);
temp = $(this).html().replace(a, "<a href='https://en.wikipedia.org/wiki/" + b + "'>" + a + "</a>");
$(this).html(temp);
}
}
});
port.postMessage({type: "to-front",data: DOMtoString(document)});
port.disconnect();
}
});
});
});
//检查是否为空字符
function checknum(value) {
var Regx = /^\s*$/;
if (Regx.test(value)) {
return true;
}
else {
return false;
}
}
//将DOM转化为String类型
function DOMtoString(document_root) {
var html = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
html += node.outerHTML;
break;
case Node.TEXT_NODE:
html += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
html += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
html += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
return html;
}
//如果不需要将javascript 和css注入到每一个匹配的网页里面,可以通过程序来控制代码的注入。
//例如, 可以只在用户点击了一个browser action图标后才注入脚本。
chrome.browserAction.onClicked.addListener(function(tab) {
// No tabs or host permissions needed!
console.log(tab.document);
//一般来说,可以将需要执行的代码放在文件里面注入,可以这样写:
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, function() {
// If you try and inject into an extensions page or the webstore/NTP you'll get an error
if (chrome.runtime.lastError) {
message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
}
});
});