前幾天某懶產品經理提出了一個懶需求,大概是這樣的:想從我們公司的cms后台點擊進入另一個第三方后台的同時,將cms后台的一些數據自動填充到那個第三方后台的一些表單中。也就是說,以前他們需要把數據、文字一個一個拷貝粘貼到第三方后台,現在他們不干了,想讓我幫他們實現這個自動“搬遷”數據的過程。這該怎么辦呢?那個第三方后台也不是我能控制的了的啊,這時就要使用chrome擴展程序這個神器了,它可以實現瀏覽器上多個頁面之間的數據傳遞呢!
關於chrome擴展程序的開發,網上有一個比較完整的中文翻譯的開發文檔——http://open.chrome.360.cn/extension_dev/overview.html,有興趣可以翻閱一下。chrome擴展程序能做的事情還是挺多挺好玩的,不過這篇博文我只是想以一個很簡單的例子來講解一下它的基本開發過程,從代碼編寫到加載運行,最后再說明一下整個擴展程序的運行原理以及調試。這個簡單例子是這樣的:將一些QQ郵箱的賬號密碼寫在文件中,然后進入QQ郵箱登陸界面的時候帶入一個id參數,chrome擴展程序根據這個id去讀取QQ賬號密碼自動填充到登錄表單中,無需我們手動輸入,然后這個擴展程序還要能記錄郵箱的登錄情況。廢話不多說,這就開始了!
首先創建一個空文件夾qqmail用於存放這個擴展程序所有的代碼文件,然后寫一個配置文件manifest.json,配置文件各個參數配置和意義如下:
{
"name": "QQ Mail Extention",//擴展程序名稱
"version": "1.0",//版本
"manifest_version": 2,//一定要為2,否則會報錯
"description": "This Extention can help you manifest_versionto login QQ Mail faster!",//擴展程序描述
"browser_action": {
"default_icon": "logo.png",//默認圖標
"default_popup": "popup.html"//點擊圖標時彈出的頁面
},
"background": {
"persistent": true,
"scripts": ["background.js"]//擴展程序背景頁腳本
},
"content_scripts": [{
"all_frames": true,//是否運行在頁面所有frame中,設置為true時擴展程序在iframe中也能起作用
"matches": ["*://*/*"],//定義那些頁面需要注入content script腳本
"js": ["jq.1.8.2_dev.js","content_scripts.js"]//需要向頁面注入的content script腳本
}],
"permissions": [//擴展程序權限
"tabs", "webNavigation"
]
}
說明(browser_action和page_action只能選其中一個):
browser_action:擴展程序圖標在chrome地址欄之外,chrome主工具欄右側。定義處理事件適用於所有頁面。
page_action:擴展程序圖標在chrome地址欄之內右側。定義需要處理的頁面的事件,並不是適用於所有頁面的。
擴展程序背景頁腳本:在以上配置中為background.js,是一個獨立於所有頁面的腳本,常用於管理一些任務或狀態,可作為不同頁面之間傳遞數據的橋梁。它會在擴展程序的整個生命周期都存在,同時,在同一時間只有一個實例處於活動狀態。
接下來,編寫擴展程序彈窗頁面popup.html:
<!DOCTYPE html>
<html>
<head>
<title>QQ郵箱快捷登錄插件</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
table{border-collapse:collapse}
table td{padding:5px}
</style>
</head>
<body style="height:150px;width:200px">
<h3>當前QQ郵箱信息</h3>
<div id="info"></div>
</body>
<script src="jq.1.8.2_dev.js"></script>
<script src="popup.js"></script>
</html>
popup.html中引入了兩個js文件,一個是jQuery文件,另一個則是用於刷新彈窗內容的popup.js,不過,這里要先介紹一下擴展程序背景頁腳本background.js:
var qqmail = new function() {
var I = this, info = {'hasInfo': 0},//當前郵箱信息
accounts = {//所有QQ郵箱賬號配置
1: {
'username': '2******04@qq.com',//賬號
'password': '1242444',//密碼
'password2': '341222'//獨立密碼
},
2: {
'username': '8834839@sina.com',
'password': '1234245',
'password2': '2141211'
},
3: {
'username': '8110110109@qq.com',
'password': '111111',
'password2': '222222'
}
};
I.setInfo = function(id) {//設置當前郵箱信息
if(accounts[id]) {
info = accounts[id];
info.hasInfo = 1;
I.setStatus(0);
}
};
I.setStatus = function(i) {//設置當前郵箱狀態
var status = {
0: '未登錄',
1: '還需輸入獨立密碼',
2: '已登錄',
3: '已退出登錄'
};
if(status[i]) info.status = status[i];
};
I.getInfo = function() {//獲取當前郵箱信息
return info;
};
};
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {//監聽來自content_scripts.js的消息並作出響應
var f = qqmail[request.cmd];
if(typeof f === 'function') {
var ret = f(request.par);
if(typeof sendResponse == 'function') {
sendResponse(ret);
}
}
});
這個文件主要記錄了一些QQ郵箱的賬號、密碼和獨立密碼,並維護當前登錄郵箱的登錄狀態,使用chrome.runtime.onMessage.addListener()監聽來自content script腳本的請求。
好了,現在回過頭來看看popup.js:
(function() {
var fn = function() {
var info = chrome.extension.getBackgroundPage().qqmail.getInfo(), s = '';
if(info.hasInfo) {
var cfg = {
'username': '郵箱',
'password': '密碼',
'password2': '獨立密碼',
'status': '登錄狀態'
};
s = '<table border="1">';
$.each(info, function(k, v) {
if(cfg[k]) s += '<tr><td>' + cfg[k] + '</td><td>' + v + '</td></tr>';
});
s += '</table>';
} else {
s = '尚無任何QQ郵箱信息......';
}
$('#info').html(s);
};
fn();
})();
這個js文件主要是通過chrome.extension.getBackgroundPage()與擴展程序背景頁腳本background.js取得聯系,並調用其中的qqmail.getInfo()取得當前登錄郵箱的信息,刷新彈窗頁面popup.html的內容。
最后就是content script文件content_scripts.js:
(function() {
var init = function() {
if(location.href.indexOf('https://mail.qq.com/?id=') >= 0) {//QQ郵箱登錄主頁面
var id = location.href.split('=')[1];
send('setInfo', id);//初始化當前郵箱信息
} else if(location.href.indexOf('https://xui.ptlogin2.qq.com/cgi-bin/xlogin') >= 0) {//QQ郵箱登錄表單iframe
send('getInfo', function(ret) {//獲取當前郵箱信息填充登錄表單
getObj('[name="u"]', function(o) {
o.val(ret.username);
$('[name="p"]').val(ret.password);
});
});
} else if(location.href.indexOf('https://mail.qq.com/cgi-bin/loginpage?autologin') >= 0) {//填寫QQ郵箱獨立密碼
send('setStatus', 1);//設置郵箱狀態
send('getInfo', function(ret) {//獲取當前郵箱信息填充登錄表單
getObj('[name="pp"]', function(o) {
o.val(ret.password2);
});
});
} else if(location.href.indexOf('https://mail.qq.com/cgi-bin/frame_html') >= 0) {//QQ郵箱成功登錄
send('setStatus', 2);//設置郵箱狀態
} else if(location.href.indexOf('https://mail.qq.com/cgi-bin/loginpage?t=wx_logout') >= 0) {//QQ郵箱退出登錄
send('setStatus', 3);//設置郵箱狀態
}
},
getObj = function(s, fn, tm, tmout) {//控件加載完成才獲取,防止控件尚未加載完成而導致獲取不到對象
tm = tm || 100;
var t = setInterval(function() {
var o = $(s);
if(o[0]) {
clearInterval(t);
if(tmout && tmout > 0) {
setTimeout(function() {
fn(o);
}, tmout);
} else {
fn(o);
}
}
}, tm);
};
send = function(cmd, par, cb){//給background.js發消息
if(typeof par == 'function'){
cb = par;
par = '';
}
chrome.runtime.sendMessage({cmd:cmd, par:par}, cb);
};
$(init);
})();
這個腳本是運行在chrome每一個頁面的,主要工作就是判斷當前頁面是哪個頁面並作出相應動作,使用chrome.runtime.sendMessage()從背景頁腳本請求數據、發送郵箱登陸狀態給背景頁。
好了,到這里這個簡單的chrome擴展程序便開發完成了,目錄的所有文件如下:
代碼編寫完畢之后便可以開始加載這個擴展程序來運行了,在chrome上的操作示意圖如下:
點擊“加載已解壓的擴展文件”選中剛剛的目錄qqmail,加載之后信息如下:
至此,這個簡單的chrome擴展程序已經開始運行,接下來操作一下郵箱登錄過程,並逐步說明這個擴展程序的運行過程與原理。
加載之后點擊擴展程序圖標,彈窗頁面腳本popup.js便會請求背景頁腳本background.js,獲取郵箱信息,刷新彈窗頁面內容,由於此時還沒有進入QQ郵箱登錄頁面並傳id參數,所以background.js中還沒有當前登錄郵箱的任何信息,所以彈窗頁面是這樣的:
接下來打開QQ郵箱登錄頁面並傳id,比如這樣:https://mail.qq.com/?id=1,進入這個頁面之后content script腳本content_scripts.js通過url匹配找到要執行的動作,即:取得參數id的值,並調用背景頁腳本background.js的qqmail.setInfo()函數,取得當前要登錄郵箱的信息並保存在info對象中。這時,由於QQ郵箱登錄表單位於登錄頁面中的iframe中,擴展程序的content script腳本content_scripts.js也運行其中,通過腳本中第二個url匹配,發送消息給背景頁腳本background.js,調用其中的qqmail.getInfo()函數取得info對象中的賬號和密碼,自動填充到登錄表單中,這樣就無需我們手動輸入了。此時再去點擊擴展程序圖標,彈窗腳本popup.js再次請求背景頁腳本background.js中的qqmail.getInfo()函數獲取當前登錄QQ郵箱信息,刷新彈窗頁面,效果是這樣的:
接下來,點擊登錄,進入獨立密碼填寫頁面,content script腳本content_scripts.js通過與背景頁腳本background.js通信,做兩個動作:首先調用qqmail.setStatus()函數設置郵箱登錄狀態,然后調用qqmail.getInfo()函數取得獨立密碼並自動填充表單。此時再點擊擴展程序圖標,popup.js重新請求背景頁腳本刷新彈窗頁面如下:
同樣的,登錄成功、退出登錄時,content script腳本content_scripts.js也都會發消息給背景頁腳本background.js去修改當前登錄郵箱的登錄狀態,即更新info對象的值,點擊擴展圖標時彈窗頁面腳本popup.js也會請求背景頁腳本background.js獲取當前登錄郵箱狀態,刷新彈窗頁面。
好了,現在大概了解chrome擴展程序大概的運作原理了吧。整個擴展程序主要涉及三個js腳本文件:
1. 彈窗頁面腳本:每點擊一次擴展程序圖標則運行一次,主要負責通過與背景頁腳本通信,請求數據,刷新彈窗內容。
2. content script腳本:運行於chrome中每個打開的頁面,可與背景頁腳本通信,可操作當前頁面。
3. 背景頁腳本:獨立於chrome任何頁面,存在於擴展程序整個生命周期,一般用於保存一些數據狀態,充當不同頁面之間數據交流的橋梁。
最后,簡單說一下chrome擴展程序開發過程中的調試方法。彈窗頁面腳本的調試方法:右鍵擴展圖標,點擊“審查彈出內容”即可彈出調試窗口,對彈窗頁面進行抓包。content script腳本的調試方法則與一般調試相同,直接按“F12”按鈕即可。而背景頁腳本,由於沒有具體頁面,故無法直接調試,可通過彈窗頁面腳本和 content script腳本使用一定方法間接調試,因為這兩個腳本都可獲取到背景頁腳本中的數據啊。修改了擴展程序代碼之后,保存,然后直接在chrome擴展程序管理頁面點擊“重新加載”即可生效!
其實chrome擴展程序能做的事情還真挺多的,本文只是提供了一個很簡單的例子來說明它的開發過程與運行過程而已。一般來說,我們可以通過在某個第三方網頁的url末尾加上我們自定義的參數,由我們的chrome擴展程序的content script腳本根據這個參數去請求我們自己的接口,獲取數據來填充這個網頁的表單,或是做一些其他的操作來達到我們的目的,也可以在content script腳本中定義某個頁面的某個按鈕的點擊事件,在事件響應函數中就可以做我們想做的事情就是了,當然了,操作頁面上的內容之前,首先要先研究一下這個頁面的html代碼,不然你怎么知道去操作哪些控件呢是吧。
本文到此結束,所述內容如有不妥,敬請諒解,歡迎指教,哈哈!