6.6 编写第一个Chrome应用
在编写Chrome应用时请时刻记住,这已经不是单纯地开发浏览器扩展了,现在要编写的是一款真正的桌面程序,而Chrome只是类似CLR和Java的环境而已。
下面我们来一起编写一个计算机性能监视器。
首先来创建Manifest文件:
{
"app": {
"background": {
"scripts": ["background.js"]
}
},
"manifest_version": 2,
"name": "Performance Monitor",
"version": "1.0",
"description": "A performance monitor to show cpu and memory status.",
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
},
"permissions": [
"system.cpu",
"system.memory"
]
}
下面编写background.js脚本,根据6.5的内容可以直接写出如下代码:
chrome.app.runtime.onLaunched.addListener(function() {
chrome.app.window.create('main.html', {
'id': 'main',
'bounds': {
'width': 542,
'height': 360
},
'resizable': false,
'frame': 'none'
});
});
同理,main.html中的自定义菜单我们也用上一节提到的代码,但取消最大化按钮。为绘制曲线和饼图,本例使用了一个JS图表库,Chart.js,有关Chart.js的详细内容可以通过http://www.bootcss.com/p/chart.js/查看。
下面是main.html的代码:
<html>
<head>
<title>Performance Monitor</title>
<style>
body {
margin: 0;
padding: 0;
border: #EEE 1px solid;
}
#title_bar {
-webkit-app-region: drag;
height: 22px;
line-height: 22px;
font-size: 16px;
background: #EEE;
padding: 0 10px;
box-sizing: border-box;
}
#title_bar a {
-webkit-app-region: no-drag;
display: inline-block;
float: right;
height: 12px;
width: 12px;
margin: 5px;
border: gray 1px solid;
box-sizing: border-box;
border-radius: 6px;
}
#title_bar a:hover {
background: gray;
}
#box_body {
padding: 20px;
}
.chart {
margin-bottom: 20px;
font-size: 0;
}
.usage_item {
color: gray;
padding: 2px 0;
font-size: 14px;
border-bottom: #EEE 1px solid;
margin-bottom: 4px;
}
</style>
</head>
<body>
<div id="title_bar">Performance Monitor
<a id="close" href="#"></a>
<a id="minimize" href="#"></a>
</div>
<div id="box_body">
<div class="usage_item">CPU Usage</div>
<div class="chart">
<canvas id="cpu_total" width="100" height="100"></canvas>
<canvas id="cpu_history" width="400" height="100"></canvas>
</div>
<div class="usage_item">Memory Usage</div>
<div class="chart">
<canvas id="mem_total" width="100" height="100"></canvas>
<canvas id="mem_history" width="400" height="100"></canvas>
</div>
</div>
<script src="control.js"></script>
<script src="Chart.js"></script>
<script src="main.js"></script>
</body>
</html>
其中的canvas
用来展示数据。
control.js的代码:
var current_window = chrome.app.window.current();
document.getElementById('minimize').onclick = function(){
current_window.minimize();
}
document.getElementById('close').onclick = function(){
current_window.close();
}
下面来编写main.js,这个脚本用来定时获取数据并进行展示。
function getCpuUsage(callback){
chrome.system.cpu.getInfo(function(info){
var total = 0;
var user = 0;
var kernel = 0;
for(var i=0; i<info.processors.length; i++){
total += info.processors[i].usage.total - cpu_history.last_total[i];
cpu_history.last_total[i] = info.processors[i].usage.total;
user += info.processors[i].usage.user - cpu_history.last_user[i];
cpu_history.last_user[i] = info.processors[i].usage.user;
kernel += info.processors[i].usage.kernel - cpu_history.last_kernel[i];
cpu_history.last_kernel[i] = info.processors[i].usage.kernel;
}
user = Math.round(user/total*100);
kernel = Math.round(kernel/total*100);
callback({user:user,kernel:kernel,total:user+kernel});
});
}
function getMemUsage(callback){
chrome.system.memory.getInfo(function(info){
callback(info);
});
}
function updateCpuHistory(){
getCpuUsage(function(usage){
cpu_history.user.shift();
cpu_history.user.push(usage.user);
cpu_history.kernel.shift();
cpu_history.kernel.push(usage.kernel);
cpu_history.total.shift();
cpu_history.total.push(usage.total);
showCpu();
});
}
function updateMemHistory(){
getMemUsage(function(usage){
mem_history.used.shift();
mem_history.used.push(Math.round((usage.capacity-usage.availableCapacity)/usage.capacity*100));
showMem();
});
}
function updateData(){
updateCpuHistory();
updateMemHistory();
}
function showCpu(){
var history = {
labels : (function(){for(var i=0,labels=[];i<ponits_num;labels.push(''),i++);return labels;})(),
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
data : cpu_history.total
},
{
fillColor : "rgba(90,140,255,0.5)",
data : cpu_history.kernel
},
{
fillColor : "rgba(255,90,90,0.5)",
data : cpu_history.user
}
]
};
var now = [
{
value: cpu_history.total[ponits_num-1],
color:"rgba(220,220,220,0.7)"
},
{
value : 100-cpu_history.total[ponits_num-1],
color : "rgba(220,220,220,0.3)"
}
];
var his_ctx = document.getElementById('cpu_history').getContext("2d");
var now_ctx = document.getElementById("cpu_total").getContext("2d");
new Chart(his_ctx).Line(history, {scaleFontSize:4,pointDot:false,animation:false});
new Chart(now_ctx).Pie(now, {segmentShowStroke:false,animation:false});
}
function showMem(){
var history = {
labels : (function(){for(var i=0,labels=[];i<ponits_num;labels.push(''),i++);return labels;})(),
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
data : mem_history.used
}
]
};
var now = [
{
value: mem_history.used[ponits_num-1],
color:"rgba(220,220,220,0.7)"
},
{
value : 100-mem_history.used[ponits_num-1],
color : "rgba(220,220,220,0.3)"
}
];
var his_ctx = document.getElementById('mem_history').getContext("2d");
var now_ctx = document.getElementById("mem_total").getContext("2d");
new Chart(his_ctx).Line(history, {scaleFontSize:4,pointDot:false,animation:false});
new Chart(now_ctx).Pie(now, {segmentShowStroke:false,animation:false});
}
function init(){
cpu_history = {
user: [],
kernel: [],
total: [],
last_user: [],
last_kernel: [],
last_total: []
};
mem_history = {
used: []
};
init_cpu_history();
}
function init_cpu_history(){
for(var i=0; i<ponits_num; i++){
cpu_history.user.push(0);
cpu_history.kernel.push(0);
cpu_history.total.push(0);
}
chrome.system.cpu.getInfo(function(info){
for(var i=0; i<info.processors.length; i++){
cpu_history.last_total.push(info.processors[i].usage.total);
cpu_history.last_user.push(info.processors[i].usage.user);
cpu_history.last_kernel.push(info.processors[i].usage.kernel);
}
init_mem_history();
});
}
function init_mem_history(){
for(var i=0; i<ponits_num; i++){
mem_history.used.push(0);
}
updateData();
setInterval(updateData, 1000);
}
var cpu_history, mem_history, ponits_num=20;
init();
其中getCpuUsage
和getMemUsage
函数分别用于获取CPU和内存的使用量。值得注意的是,Chrome返回的CPU使用量是累计使用时间,并不是获取瞬间的CPU占用量,所以需要对前后两个时间点获得的结果做差。showCpu
和showMem
方法将获取的数据显示成图表,两个函数都是参照Chart.js文档编写的,感兴趣的读者可以自行查阅。
另外Chart.js本身有new Function声明函数的部分,由于之前介绍的CSP规则,这在Chrome应用中是不被允许的,所以本例中的Chart.js是编者改写后的,具体差异读者可以下载后自行对照。在以后编写Chrome应用引用现成的库时,可能会经常遇到由于CSP的限制而无法直接运行的情况,这需要读者拥有自行更改库代码的能力。
本例应用运行的截图如下所示:
Performance Monitor运行截图
本节中讲解的实例的源代码可以通过https://github.com/sneezry/chrome_extensions_and_apps_programming/tree/master/performance%20monitor下载到。