Chrome 瀏覽器外掛之監控網頁地址
阿新 • • 發佈:2018-12-27
瀏覽器外掛開發手冊:http://open.chrome.360.cn/extension_dev/overview.html
瀏覽器外掛demo,請先參考部落格:https://www.cnblogs.com/liuxianan/p/chrome-plugin-develop.html
注意事項,由於js和C++的差異性,導致踩了不少坑: 1.js如果提及預設值,請填寫null。 坑:chrome.tabs.getAllInWindow(integer windowId, function callback) windowId 預設為當前視窗 然後給了一個連線值:chrome.windows.WINDOW_ID_NONE,此時發現獲取不到資料。如果引數給null就對了 2.js函式執行順序是非同步的,並不會等待,所以需要使用回撥,返回值不一定是正確的。如下通過函式返回值判斷標籤是否存在的方式是錯誤的: 錯誤方式: function isExistTab() { //block1 var bExist = false; chrome.tabs.getAllInWindow(null, function(tabs) { //block2 for ( var i = 0; i <tabs.length; i++) { url = tabs[i].url; if(url.indexOf("pan.bitqiu.com") != -1) { bexist = true; break; } } }); //block3 return bExist ; } 除錯你會發現,程式碼執行順序是block1=》block3=》block2 ,並不是順序執行 3.js中的try catch 只會抓當前程式碼塊的異常,並不會捕獲程式碼塊裡面的函式的異常 function test() { try { .... .... //這段function程式碼的異常不會被捕獲 function() { try{} catch(e){} } } catch(e) { } }
首先我們需要學習參考手冊,瞭解基本的外掛包格式和物件介面。監控瀏覽器網頁地址可以參考瀏覽器外掛demo學習裡面的使用方法。
開發思考?
- 如何需要監控瀏覽器請求發生變化?
- 如何開啟標籤頁,判斷標籤頁是否存在?
問題1:如何需要監控瀏覽器請求發生變化?
答:首先監控瀏覽器請求那麼生命週期必須和瀏覽器共存,才能在整體上監控瀏覽器請求變化。
那麼首先可以排除popup裡面處理js,所以我們把目標轉移到content.js 和 background.js, 但是根據手冊我們:
下面是content scipt可以做的一些事情範例: 從頁面中找到沒有寫成超連結形式的url,並將它們轉成超連結。 放大頁面字型使文字更清晰 找到並處理DOM中的microformat 當然,content scripts也有一些限制,它們不能做的事情包括 : 不能使用除了chrome.extension之外的chrome.* 的介面 不能訪問它所在擴充套件中定義的函式和變數 不能訪問web頁面或其它content script中定義的函式和變數 不能做cross-site XMLHttpRequests 這些限制其實並不像看上去那麼糟糕。Content scripts 可以使用messages機制與它所在的擴充套件通訊,來間接使用chrome.*介面,或訪問擴充套件資料。Content scripts還可以通過共享的DOM來與web頁面通訊。更多功能參見執行環境。
所以我們在content.js裡面沒有辦法處理和標籤頁相關的事物。但是可以使用messages機制和其他擴充套件通訊。message 需要json格式字串
document.addEventListener('DOMContentLoaded', function() { try { //alert(JSON.stringify(document)); //按照匹配規則匹配 //if(location.href == 'https://www.baidu.com/') //傳送訊息,有backgrand處理 chrome.runtime.sendMessage({greeting:location.href}, function(response) { }); } catch(e) { alert(e); } });
問題1:如何開啟標籤頁?
答:通過問題1我們可以知道如果處理messge的話,最好的方式就是在background.js裡面處理message,因為background.js可以很輕鬆的和標籤頁互動,並且處理標籤頁的事務。
// 監聽來自content-script的訊息
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
//{greeting:url}
try
{
var url = request.greeting;
//url.match()
isExistTab(bExist =>{
if(bExist)
{
//alert(url);
}
else
{
//如果不存在開啟新的標籤頁
openUrlNewTab("https://pan.bitqiu.com/");
}
});
}
catch(e)
{
alert(e);
}
sendResponse('ans:ok');
});
// 獲取當前選項卡ID
function getCurrentTabId(callback)
{
chrome.tabs.query({active: true, currentWindow: true}, function(tabs)
{
if(callback) callback(tabs.length ? tabs[0].id: null);
});
}
// 當前標籤開啟某個連結
function openUrlCurrentTab(url)
{
getCurrentTabId(tabId => {
chrome.tabs.update(tabId, {url: url});
})
}
// 新標籤開啟某個連結
function openUrlNewTab(url)
{
chrome.tabs.create({url: url});
}
//判斷某個標籤頁是否存在
function isExistTab(callback)
{
chrome.tabs.getAllInWindow(null, function(tabs)
{
bexist = false;
for ( var i = 0; i <tabs.length; i++)
{
url = tabs[i].url;
if(url.indexOf("pan.bitqiu.com") != -1)
{
bexist = true;
break;
}
}
if(callback) callback(bexist)
});
}
現在就是配置外掛manifest.json
{
"manifest_version": 2,
"name": "watch_url_redirect",
"description": "watch url address if is match role and open a new tab ",
"version": "1.0.2",
"icons":
{
"16": "img/icon.png",
"48": "img/icon.png",
"128": "img/icon.png"
},
"background":
{
"scripts": ["js/background.js"]
},
"browser_action":
{
"default_icon": "img/icon.png",
"default_title": "stwatch",
"default_popup": "popup.html"
},
// 需要直接注入頁面的JS
"content_scripts":
[
{
// "<all_urls>" 表示匹配所有地址
"matches": ["<all_urls>"],
// 多個JS按順序注入
"js": ["js/content-script.js"],
// 程式碼注入的時間,可選值: "document_start", "document_end", or "document_idle",最後一個表示頁面空閒時,預設document_idle
"run_at": "document_start"
}
],
// 許可權申請
"permissions":
[
"contextMenus", // 右鍵選單
"tabs", // 標籤
"notifications", // 通知
"webRequest", // web請求
"webRequestBlocking", // 阻塞式web請求
"storage", // 外掛本地儲存
"http://*/*", // 可以通過executeScript或者insertCSS訪問的網站
"https://*/*" // 可以通過executeScript或者insertCSS訪問的網站
]
}
此時整個外掛完成請求監控。
思考:
其實在寫background.js的時候我發現事實我們可以監控:chrome.webRequest.onBeforeRequest.addListener,但是不知道為什麼這個介面沒有被觸發,所以使用了message機制來實現。等後面有時間研究在來解決這個問題.