1.browserAction(瀏覽器右上角)
通過配置browser_action
可以在瀏覽器的右上角增加一個圖標(biāo),一個browser_action
可以擁有一個圖標(biāo)械媒,一個tooltip
朗若,一個badge
和一個popup
桶雀。
示例配置如下:
"browser_action":
{
"default_icon": "img/icon.png",
"default_title": "這是一個示例Chrome插件",
"default_popup": "popup.html"
}
1.1 圖標(biāo)
browser_action
圖標(biāo)推薦使用寬高都為19像素的圖片,更大的圖標(biāo)會被縮小只嚣,格式隨意灿渴,一般推薦png洛波,可以通過manifest中default_icon
字段配置胰舆,也可以調(diào)用setIcon()方法。
1.2 tooltip
修改browser_action
的manifest中default_title
字段蹬挤,或者調(diào)用setTitle()
方法缚窿。
1.3 badge
所謂badge
就是在圖標(biāo)上顯示一些文本,可以用來更新一些小的擴(kuò)展?fàn)顟B(tài)提示信息焰扳。因為badge空間有限倦零,所以只支持4個以下的字符(英文4個,中文2個)吨悍。badge無法通過配置文件來指定扫茅,必須通過代碼實現(xiàn),設(shè)置badge文字和顏色可以分別使用setBadgeText()
和setBadgeBackgroundColor()
育瓜。
chrome.browserAction.setBadgeText({text: 'new'});
chrome.browserAction.setBadgeBackgroundColor({color: [255, 0, 0, 255]});
效果:
2. pageAction(地址欄右側(cè))
所謂pageAction
葫隙,指的是只有當(dāng)某些特定頁面打開才顯示的圖標(biāo),它和browserAction
最大的區(qū)別是一個始終都顯示躏仇,一個只在特定情況才顯示恋脚。
需要特別說明的是早些版本的Chrome是將pageAction放在地址欄的最右邊,左鍵單擊彈出popup焰手,右鍵單擊則彈出相關(guān)默認(rèn)的選項菜單:
而新版的Chrome更改了這一策略糟描,pageAction和普通的browserAction一樣也是放在瀏覽器右上角,只不過沒有點亮?xí)r是灰色的书妻,點亮了才是彩色的船响,灰色時無論左鍵還是右鍵單擊都是彈出選項:
具體是從哪一版本開始改的沒去仔細(xì)考究,反正知道v50.0的時候還是前者躲履,v58.0的時候已改為后者灿意。
調(diào)整之后的pageAction
我們可以簡單地把它看成是可以置灰的browserAction
。
- chrome.pageAction.show(tabId) 顯示圖標(biāo)崇呵;
- chrome.pageAction.hide(tabId) 隱藏圖標(biāo);
示例(只有打開百度才顯示圖標(biāo)):
// manifest.json
{
"page_action":
{
"default_icon": "img/icon.png",
"default_title": "我是pageAction",
"default_popup": "popup.html"
},
"permissions": ["declarativeContent"]
}
// background.js
chrome.runtime.onInstalled.addListener(function(){
chrome.declarativeContent.onPageChanged.removeRules(undefined, function(){
chrome.declarativeContent.onPageChanged.addRules([
{
conditions: [
// 只有打開百度才顯示pageAction
new chrome.declarativeContent.PageStateMatcher({pageUrl: {urlContains: 'baidu.com'}})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}
]);
});
});
效果圖:
3.右鍵菜單
通過開發(fā)Chrome插件可以自定義瀏覽器的右鍵菜單馅袁,主要是通過chrome.contextMenus
API實現(xiàn)域慷,右鍵菜單可以出現(xiàn)在不同的上下文,比如普通頁面汗销、選中的文字犹褒、圖片、鏈接弛针,等等叠骑,如果有同一個插件里面定義了多個菜單,Chrome會自動組合放到以插件名字命名的二級菜單里削茁,如下:
3.1. 最簡單的右鍵菜單示例
// manifest.json
{"permissions": ["contextMenus"]}
// background.js
chrome.contextMenus.create({
title: "測試右鍵菜單",
onclick: function(){alert('您點擊了右鍵菜單宙枷!');}
});
效果:
3.2. 添加右鍵百度搜索
// manifest.json
{"permissions": ["contextMenus"掉房, "tabs"]}
// background.js
chrome.contextMenus.create({
title: '使用度娘搜索:%s', // %s表示選中的文字
contexts: ['selection'], // 只有當(dāng)選中文字時才會出現(xiàn)此右鍵菜單
onclick: function(params)
{
// 注意不能使用location.href,因為location是屬于background的window對象
chrome.tabs.create({url: 'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(params.selectionText)});
}
});
效果如下:
3.3. 語法說明
這里只是簡單列舉一些常用的慰丛,完整API參見:https://developer.chrome.com/extensions/contextMenus
chrome.contextMenus.create({
type: 'normal'卓囚, // 類型,可選:["normal", "checkbox", "radio", "separator"]诅病,默認(rèn) normal
title: '菜單的名字', // 顯示的文字哪亿,除非為“separator”類型否則此參數(shù)必需,如果類型為“selection”贤笆,可以使用%s顯示選定的文本
contexts: ['page'], // 上下文環(huán)境蝇棉,可選:["all", "page", "frame", "selection", "link", "editable", "image", "video", "audio"],默認(rèn)page
onclick: function(){}, // 單擊時觸發(fā)的方法
parentId: 1, // 右鍵菜單項的父菜單項ID芥永。指定父菜單項將會使此菜單項成為父菜單項的子菜單
documentUrlPatterns: 'https://*.baidu.com/*' // 只在某些頁面顯示此右鍵菜單
});
// 刪除某一個菜單項
chrome.contextMenus.remove(menuItemId)篡殷;
// 刪除所有自定義右鍵菜單
chrome.contextMenus.removeAll();
// 更新某一個菜單項
chrome.contextMenus.update(menuItemId, updateProperties);
4. override(覆蓋特定頁面)
使用override
頁可以將Chrome默認(rèn)的一些特定頁面替換掉,改為使用擴(kuò)展提供的頁面恤左。
擴(kuò)展可以替代如下頁面:
- 歷史記錄:從工具菜單上點擊歷史記錄時訪問的頁面贴唇,或者從地址欄直接輸入 chrome://history
- 新標(biāo)簽頁:當(dāng)創(chuàng)建新標(biāo)簽的時候訪問的頁面,或者從地址欄直接輸入 chrome://newtab
- 書簽:瀏覽器的書簽飞袋,或者直接輸入 chrome://bookmarks
注意:
- 一個擴(kuò)展只能替代一個頁面戳气;
- 不能替代隱身窗口的新標(biāo)簽頁;
- 網(wǎng)頁必須設(shè)置title巧鸭,否則用戶可能會看到網(wǎng)頁的URL瓶您,造成困擾;
下面的截圖是默認(rèn)的新標(biāo)簽頁和被擴(kuò)展替換掉的新標(biāo)簽頁纲仍。
代碼(注意呀袱,一個插件只能替代一個默認(rèn)頁,以下僅為演示):
"chrome_url_overrides":
{
"newtab": "newtab.html",
"history": "history.html",
"bookmarks": "bookmarks.html"
}
5. devtools(開發(fā)者工具)
5.1. 預(yù)熱
使用過vue的應(yīng)該見過這種類型的插件:
是的郑叠,Chrome允許插件在開發(fā)者工具(devtools)上動手腳夜赵,主要表現(xiàn)在:
- 自定義一個和多個和
Elements
、Console
乡革、Sources
等同級別的面板寇僧; - 自定義側(cè)邊欄(sidebar),目前只能自定義
Elements
面板的側(cè)邊欄沸版;
先來看2張簡單的demo截圖嘁傀,自定義面板(判斷當(dāng)前頁面是否使用了jQuery):
自定義側(cè)邊欄(獲取當(dāng)前頁面所有圖片):
5.2. devtools擴(kuò)展介紹
主頁:https://developer.chrome.com/extensions/devtools
來一張官方圖片:
每打開一個開發(fā)者工具窗口,都會創(chuàng)建devtools頁面的實例视粮,F(xiàn)12窗口關(guān)閉细办,頁面也隨著關(guān)閉,所以devtools頁面的生命周期和devtools窗口是一致的蕾殴。devtools頁面可以訪問一組特有的DevTools API
以及有限的擴(kuò)展API笑撞,這組特有的DevTools API
只有devtools頁面才可以訪問岛啸,background都無權(quán)訪問,這些API包括:
-
chrome.devtools.panels
:面板相關(guān)娃殖; -
chrome.devtools.inspectedWindow
:獲取被審查窗口的有關(guān)信息值戳; -
chrome.devtools.network
:獲取有關(guān)網(wǎng)絡(luò)請求的信息;
大部分?jǐn)U展API都無法直接被DevTools
頁面調(diào)用炉爆,但它可以像content-script
一樣直接調(diào)用chrome.extension
和chrome.runtime
API堕虹,同時它也可以像content-script
一樣使用Message交互的方式與background頁面進(jìn)行通信。
5.3. 實例:創(chuàng)建一個devtools擴(kuò)展
首先芬首,要針對開發(fā)者工具開發(fā)插件赴捞,需要在清單文件聲明如下:
{
// 只能指向一個HTML文件,不能是JS文件
"devtools_page": "devtools.html"
}
這個devtools.html
里面一般什么都沒有郁稍,就引入一個js:
<!DOCTYPE html>
<html>
<head></head>
<body>
<script type="text/javascript" src="js/devtools.js"></script>
</body>
</html>
可以看出來赦政,其實真正代碼是devtools.js
,html文件是“多余”的耀怜,所以這里覺得有點坑恢着,devtools_page
干嘛不允許直接指定JS呢?
再來看devtools.js的代碼:
// 創(chuàng)建自定義面板财破,同一個插件可以創(chuàng)建多個自定義面板
// 幾個參數(shù)依次為:panel標(biāo)題掰派、圖標(biāo)(其實設(shè)置了也沒地方顯示)、要加載的頁面左痢、加載成功后的回調(diào)
chrome.devtools.panels.create('MyPanel', 'img/icon.png', 'mypanel.html', function(panel)
{
console.log('自定義面板創(chuàng)建成功靡羡!'); // 注意這個log一般看不到
});
// 創(chuàng)建自定義側(cè)邊欄
chrome.devtools.panels.elements.createSidebarPane("Images", function(sidebar)
{
// sidebar.setPage('../sidebar.html'); // 指定加載某個頁面
sidebar.setExpression('document.querySelectorAll("img")', 'All Images'); // 通過表達(dá)式來指定
//sidebar.setObject({aaa: 111, bbb: 'Hello World!'}); // 直接設(shè)置顯示某個對象
});
setPage時的效果:
以下截圖示例的代碼:
// 檢測jQuery
document.getElementById('check_jquery').addEventListener('click', function()
{
// 訪問被檢查的頁面DOM需要使用inspectedWindow
// 簡單例子:檢測被檢查頁面是否使用了jQuery
chrome.devtools.inspectedWindow.eval("jQuery.fn.jquery", function(result, isException)
{
var html = '';
if (isException) html = '當(dāng)前頁面沒有使用jQuery。';
else html = '當(dāng)前頁面使用了jQuery俊性,版本為:'+result;
alert(html);
});
});
// 打開某個資源
document.getElementById('open_resource').addEventListener('click', function()
{
chrome.devtools.inspectedWindow.eval("window.location.href", function(result, isException)
{
chrome.devtools.panels.openResource(result, 20, function()
{
console.log('資源打開成功略步!');
});
});
});
// 審查元素
document.getElementById('test_inspect').addEventListener('click', function()
{
chrome.devtools.inspectedWindow.eval("inspect(document.images[0])", function(result, isException){});
});
// 獲取所有資源
document.getElementById('get_all_resources').addEventListener('click', function()
{
chrome.devtools.inspectedWindow.getResources(function(resources)
{
alert(JSON.stringify(resources));
});
});
5.4. 調(diào)試技巧
修改了devtools頁面的代碼時,需要先在 chrome://extensions 頁面按下Ctrl+R
重新加載插件定页,然后關(guān)閉再打開開發(fā)者工具即可免都,無需刷新頁面(而且只刷新頁面不刷新開發(fā)者工具的話是不會生效的)魁兼。
由于devtools本身就是開發(fā)者工具頁面日麸,所以幾乎沒有方法可以直接調(diào)試它顾瞻,直接用 chrome-extension://extid/devtools.html"
的方式打開頁面肯定報錯,因為不支持相關(guān)特殊API宫峦,只能先自己寫一些方法屏蔽這些錯誤,調(diào)試通了再放開玫鸟。
6. option(選項頁)
所謂options
頁导绷,就是插件的設(shè)置頁面,有2個入口屎飘,一個是右鍵圖標(biāo)有一個“選項”菜單妥曲,還有一個在插件管理頁面:
在Chrome40以前贾费,options頁面和其它普通頁面沒什么區(qū)別,Chrome40以后則有了一些變化檐盟。
我們先看老版的options:
{
// Chrome40以前的插件配置頁寫法
"options_page": "options.html",
}
這個頁面里面的內(nèi)容就隨你自己發(fā)揮了褂萧,配置之后在插件管理頁就會看到一個選項
按鈕入口,點進(jìn)去就是打開一個網(wǎng)頁葵萎,沒啥好講的导犹。
效果:
再來看新版的optionsV2:
{
"options_ui":
{
"page": "options.html",
// 添加一些默認(rèn)的樣式,推薦使用
"chrome_style": true
},
}
options.html
的代碼我們沒有任何改動羡忘,只是配置文件改了谎痢,之后效果如下:
看起來是不是高大上了?
幾點注意:
- 為了兼容卷雕,建議2種都寫节猿,如果都寫了,Chrome40以后會默認(rèn)讀取新版的方式漫雕;
- 新版options中不能使用alert滨嘱;
- 數(shù)據(jù)存儲建議用chrome.storage,因為會隨用戶自動同步浸间;
7. omnibox
omnibox
是向用戶提供搜索建議的一種方式太雨。先來看個gif
圖以便了解一下這東西到底是個什么鬼:
注冊某個關(guān)鍵字以觸發(fā)插件自己的搜索建議界面,然后可以任意發(fā)揮了发框。
首先躺彬,配置文件如下:
{
// 向地址欄注冊一個關(guān)鍵字以提供搜索建議,只能設(shè)置一個關(guān)鍵字
"omnibox": { "keyword" : "go" },
}
然后background.js
中注冊監(jiān)聽事件:
// omnibox 演示
chrome.omnibox.onInputChanged.addListener((text, suggest) => {
console.log('inputChanged: ' + text);
if(!text) return;
if(text == '美女') {
suggest([
{content: '中國' + text, description: '你要找“中國美女”嗎梅惯?'},
{content: '日本' + text, description: '你要找“日本美女”嗎宪拥?'},
{content: '泰國' + text, description: '你要找“泰國美女或人妖”嗎?'},
{content: '韓國' + text, description: '你要找“韓國美女”嗎铣减?'}
]);
}
else if(text == '微博') {
suggest([
{content: '新浪' + text, description: '新浪' + text},
{content: '騰訊' + text, description: '騰訊' + text},
{content: '搜狐' + text, description: '搜索' + text},
]);
}
else {
suggest([
{content: '百度搜索 ' + text, description: '百度搜索 ' + text},
{content: '谷歌搜索 ' + text, description: '谷歌搜索 ' + text},
]);
}
});
// 當(dāng)用戶接收關(guān)鍵字建議時觸發(fā)
chrome.omnibox.onInputEntered.addListener((text) => {
console.log('inputEntered: ' + text);
if(!text) return;
var href = '';
if(text.endsWith('美女')) + text;
else if(text.startsWith('百度搜索')) + text.replace('百度搜索 ', '');
else if(text.startsWith('谷歌搜索')) + text.replace('谷歌搜索 ', '');
else + text;
openUrlCurrentTab(href);
});
// 獲取當(dāng)前選項卡ID
function getCurrentTabId(callback)
{
chrome.tabs.query({active: true, currentWindow: true}, function(tabs)
{
if(callback) callback(tabs.length ? tabs[0].id: null);
});
}
// 當(dāng)前標(biāo)簽打開某個鏈接
function openUrlCurrentTab(url)
{
getCurrentTabId(tabId => {
chrome.tabs.update(tabId, {url: url});
})
}
8. 桌面通知
Chrome提供了一個chrome.notifications
API以便插件推送桌面通知她君,暫未找到chrome.notifications
和HTML5自帶的Notification
的顯著區(qū)別及優(yōu)勢。
在后臺JS中葫哗,無論是使用chrome.notifications
還是Notification
都不需要申請權(quán)限(HTML5方式需要申請權(quán)限)缔刹,直接使用即可。
最簡單的通知:
代碼:
chrome.notifications.create(null, {
type: 'basic',
iconUrl: 'img/icon.png',
title: '這是標(biāo)題',
message: '您剛才點擊了自定義右鍵菜單劣针!'
});
通知的樣式可以很豐富:
這個沒有深入研究校镐,有需要的可以去看官方文檔。