最近我们需要针对google play console 收集到的崩溃堆栈信息进行处理
准备编写浏览器插件。
跟着例子先过一遍 https://www.jianshu.com/p/51c650f98d9c
然后下载脚手架```bash
git clone https://github.com/EmailThis/extension-boilerplate.git
```bash
npm install
npm run build
浏览器->工具->管理扩展->开发者模式->加载已解压的扩展程序
到这里首先需要了解一些必须的知识才能进行下去,例如
插件如何获取页面信息?
如何模拟操作页面?
如何打开新的标签页?
js间怎么访问?
怎样才能知道堆栈信息加载完成?
node_modules文件夹是什么
怎么导入模块?
数组怎么删除插入查询?
JS是否像其他语言一样拥有+= ++之类的操作?
readme.md里面写的 npm run chrome-watch 是干嘛的?
例子里面的ext.runtime.onMessage是干嘛的?看上去像是回调但是是在哪里进行的请求?
等等一大堆问题
npm run chrome-watch
首先验证这个 到底有什么用
插件间如何通信
在popup.js例子中找到以下代码,这看上去是popup.js向contentscript.js用的。能请求并返回数据,妥
ext.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, { action: 'process-page' }, renderBookmark);
});
function onRequest(request, sender, sendResponse) {
if (request.action === 'process-page') {
sendResponse(extractTags())
}
}
我尝试修改代码并保存后,点击插件,我希望它返回不一样的数据
但我失败了。原因是报了一个端口找不到的错误,我以为是我代码有问题,又改了回去,还是失败了!继续报端口错误
我尝试重启,发现又可以了。至此我发现当我需要popup.js和contentscript.js通信的时候需要重启浏览器才能正常通信,具体原因未知。任务紧没空深究,之后我每一次修改都会重启一次浏览器
我尝试在contentscript.js模拟点击页面,成功了。但是某一个时间段出现端口错误,找了好久才发现是空对象报的错。但是直接报个端口错误谁知道是怎么回事???直到我在 contentscript.js 的 ext.runtime.onMessage.addListener 回调里添加了异常处理,才终于能正确获得报错信息,而不是见鬼的端口报错。在回调里漏了sendResponse也一样会报端口错误
function onRequest(request, sender, sendResponse) {
for (var i = 0; i < js.length; i++) {
var obj = js[i]
try {
if (request.action === obj.actionName) {
sendResponse(obj.action(request))
}
} catch (err) {
alert('error:[' + obj.actionName + ']' + err)
}
}
}
ext.runtime.onMessage.addListener(onRequest);
创建新的标签
我尝试使用 chrome.tabs.create 创建新的标签,并等待堆栈信息加载完成。但是测试了几次发现setTimeout根本就不等待
一直在不停的访问堆栈标签。因为访问堆栈页面有很大的概率出现报错,这直接导致我不停的刷新页面。
后来我留意到background.js。经测试setTimeout可以在该js内使用。于是我把标签相关的操作移到background.js
创建标签看起来这样
function CreateTabs(index) {
var data = run.listDatas[index]
if (run.isPageTest) {
run.log(data.maintext + ' num:' + data.num)
return
}
if (data.maintext.indexOf('java.lang') != -1)
return
chrome.tabs.create({ url: data.href, selected: false }, function(tab) {
createTabs.push({
tab: tab,
tabid: tab.id,
cutTabRun: false,
url: data.href,
maintext: data.maintext,
secondaryline: data.secondaryline,
count: data.num
})
})
}
把在列表获得的链接通过开启新的标签获取内容,当加载堆栈出现报错的时候就切换到其他标签页刷新并等待加载完成,以此规避报错造成的读取失败
background.js通讯
chrome.runtime.sendMessage({
action: 'startRun',
total: document.querySelector('#totalText').value,
tabid: activeTab.id,
soSelect: soSelects
}, data => {
if (data == null) {
alert('运行失败')
}
})
jenkins
读取完成当然是把so堆栈翻译为可读堆栈啊。我们是使用jenkins运行的翻译,经过商议开通了post权限使用XMLHttpRequest运行job。
使用http://localhost:8080/buildByToken/buildWithParameters链接带上token和其他参数执行job
关于jenkins的API。没错我又是现学的,在页面底下有个REST API,点进去一眼就看到JsonAPI,满心欢喜的打开,结果竟然就是个json。一时无从下手。不知道怎么获取Job运行完成后的控制台信息。。只能每个看上去类型不一样的链接都试试。之后看其他文章知道了能够直接拼接链接查询
http://localhost:8080/job/jobName/number/api/json?pretty=true通过测试发现是可行的。然后就猜怎么访问控制台输出。没错是猜。我也不知道哪里有详细讲解只能猜了。还好随便猜猜就猜到了
post: function(info) {
console.log('request :' + info.url)
console.log('data:' + info.data)
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
if (this.readyState === 4) {
console.log(this.status)
if (this.status == 201) {
console.log('request Location: ' + this.getResponseHeader('Location'))
GetLocation(info, this.getResponseHeader('Location'))
} else {
Error(info.url)
}
}
});
xhr.open('POST', info.url)
var form = new FormData();
form.append("error", info.data);
xhr.send(form)
},
}
function GetLocation(info, url) {
var settings = {
'url': url + 'api/json',
'method': 'GET'
}
info.Location = settings.url
$.ajax(settings).done(function(response) {
if (response == null) {
return;
}
try {
info.number = response.executable.number
WaitBuildComplete(info, response.executable.url)
} catch (err) {
console.log('err===================================' + err)
console.log(response)
setTimeout(() => { GetLocation(info, url) }, 100)
}
})
}
function WaitBuildComplete(info, url) {
var settings = {
'url': url + 'api/json',
'method': 'GET'
}
//console.log('request Wait Build: ' + url)
$.ajax(settings).done(function(response) {
if (response == null) {
return;
}
//console.log('waitBuild:')
if (response.result == null) {
setTimeout(() => { WaitBuildComplete(info, url) }, 100)
} else {
GetConsoleText(info, url)
}
})
}
function GetConsoleText(info, url) {
var settings = {
'url': url + 'consoleText/api/json',
'method': 'GET'
}
info.consoleTextUrl = settings.url
console.log('request: ' + settings.url)
$.ajax(settings).done(function(response) {
if (response == null) {
Error(settings.url)
return;
}
Succeed(info, response)
})
}
再之后就是等待全部执行完成在potions.html页面输出原始信息和翻译信息。顺便启动下载防止不小心操作错误页面丢失了
function downloadByBlob(fileName, content) {
let blob = new Blob([content], {
type: "text/plain;charset=utf-8"
});
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function(e) {
let a = document.createElement('a');
a.download = fileName;
a.href = e.target.result;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
}