3. Chrome插件的8種展示形式

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()方法缚窿。

image

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]});

效果:

image

2. pageAction(地址欄右側(cè))

所謂pageAction葫隙,指的是只有當(dāng)某些特定頁面打開才顯示的圖標(biāo),它和browserAction最大的區(qū)別是一個始終都顯示躏仇,一個只在特定情況才顯示恋脚。

需要特別說明的是早些版本的Chrome是將pageAction放在地址欄的最右邊,左鍵單擊彈出popup焰手,右鍵單擊則彈出相關(guān)默認(rèn)的選項菜單:

image

而新版的Chrome更改了這一策略糟描,pageAction和普通的browserAction一樣也是放在瀏覽器右上角,只不過沒有點亮?xí)r是灰色的书妻,點亮了才是彩色的船响,灰色時無論左鍵還是右鍵單擊都是彈出選項:

image

具體是從哪一版本開始改的沒去仔細(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()]
            }
        ]);
    });
});

效果圖:

image

3.右鍵菜單

通過開發(fā)Chrome插件可以自定義瀏覽器的右鍵菜單馅袁,主要是通過chrome.contextMenusAPI實現(xiàn)域慷,右鍵菜單可以出現(xiàn)在不同的上下文,比如普通頁面汗销、選中的文字犹褒、圖片、鏈接弛针,等等叠骑,如果有同一個插件里面定義了多個菜單,Chrome會自動組合放到以插件名字命名的二級菜單里削茁,如下:

image

3.1. 最簡單的右鍵菜單示例

// manifest.json
{"permissions": ["contextMenus"]}

// background.js
chrome.contextMenus.create({
    title: "測試右鍵菜單",
    onclick: function(){alert('您點擊了右鍵菜單宙枷!');}
});

效果:

image

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)});
    }
});

效果如下:

image

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)簽頁纲仍。

image

代碼(注意呀袱,一個插件只能替代一個默認(rèn)頁,以下僅為演示):

"chrome_url_overrides":
{
    "newtab": "newtab.html",
    "history": "history.html",
    "bookmarks": "bookmarks.html"
}

5. devtools(開發(fā)者工具)

5.1. 預(yù)熱

使用過vue的應(yīng)該見過這種類型的插件:

image

是的郑叠,Chrome允許插件在開發(fā)者工具(devtools)上動手腳夜赵,主要表現(xiàn)在:

  • 自定義一個和多個和ElementsConsole乡革、Sources等同級別的面板寇僧;
  • 自定義側(cè)邊欄(sidebar),目前只能自定義Elements面板的側(cè)邊欄沸版;

先來看2張簡單的demo截圖嘁傀,自定義面板(判斷當(dāng)前頁面是否使用了jQuery):

image

自定義側(cè)邊欄(獲取當(dāng)前頁面所有圖片):

image

5.2. devtools擴(kuò)展介紹

主頁:https://developer.chrome.com/extensions/devtools

來一張官方圖片:

image

每打開一個開發(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.extensionchrome.runtimeAPI堕虹,同時它也可以像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時的效果:

image

以下截圖示例的代碼:

image
// 檢測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)有一個“選項”菜單妥曲,還有一個在插件管理頁面:

image
image

在Chrome40以前贾费,options頁面和其它普通頁面沒什么區(qū)別,Chrome40以后則有了一些變化檐盟。

我們先看老版的options

{
    // Chrome40以前的插件配置頁寫法
    "options_page": "options.html",
}

這個頁面里面的內(nèi)容就隨你自己發(fā)揮了褂萧,配置之后在插件管理頁就會看到一個選項按鈕入口,點進(jìn)去就是打開一個網(wǎng)頁葵萎,沒啥好講的导犹。

效果:

image

再來看新版的optionsV2

{
    "options_ui":
    {
        "page": "options.html",
        // 添加一些默認(rèn)的樣式,推薦使用
        "chrome_style": true
    },
}

options.html的代碼我們沒有任何改動羡忘,只是配置文件改了谎痢,之后效果如下:

image

看起來是不是高大上了?

幾點注意:

  • 為了兼容卷雕,建議2種都寫节猿,如果都寫了,Chrome40以后會默認(rèn)讀取新版的方式漫雕;
  • 新版options中不能使用alert滨嘱;
  • 數(shù)據(jù)存儲建議用chrome.storage,因為會隨用戶自動同步浸间;

7. omnibox

omnibox是向用戶提供搜索建議的一種方式太雨。先來看個gif圖以便了解一下這東西到底是個什么鬼:

image

注冊某個關(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.notificationsAPI以便插件推送桌面通知她君,暫未找到chrome.notifications和HTML5自帶的Notification的顯著區(qū)別及優(yōu)勢。

在后臺JS中葫哗,無論是使用chrome.notifications還是Notification都不需要申請權(quán)限(HTML5方式需要申請權(quán)限)缔刹,直接使用即可。

最簡單的通知:

image

代碼:

chrome.notifications.create(null, {
    type: 'basic',
    iconUrl: 'img/icon.png',
    title: '這是標(biāo)題',
    message: '您剛才點擊了自定義右鍵菜單劣针!'
});

通知的樣式可以很豐富:

image

這個沒有深入研究校镐,有需要的可以去看官方文檔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捺典,一起剝皮案震驚了整個濱河市鸟廓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖引谜,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牍陌,死亡現(xiàn)場離奇詭異,居然都是意外死亡员咽,警方通過查閱死者的電腦和手機(jī)毒涧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贝室,“玉大人契讲,你說我怎么就攤上這事〉挡#” “怎么了怀泊?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長误趴。 經(jīng)常有香客問我霹琼,道長,這世上最難降的妖魔是什么凉当? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任枣申,我火速辦了婚禮,結(jié)果婚禮上看杭,老公的妹妹穿的比我還像新娘忠藤。我一直安慰自己,他們只是感情好楼雹,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布模孩。 她就那樣靜靜地躺著,像睡著了一般贮缅。 火紅的嫁衣襯著肌膚如雪榨咐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天谴供,我揣著相機(jī)與錄音块茁,去河邊找鬼。 笑死桂肌,一個胖子當(dāng)著我的面吹牛数焊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播崎场,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼佩耳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谭跨?” 一聲冷哼從身側(cè)響起干厚,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤答恶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后萍诱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡污呼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年裕坊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燕酷。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡籍凝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苗缩,到底是詐尸還是另有隱情饵蒂,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布酱讶,位于F島的核電站退盯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏泻肯。R本人自食惡果不足惜渊迁,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灶挟。 院中可真熱鬧琉朽,春花似錦、人聲如沸稚铣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惕医。三九已至耕漱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曹锨,已是汗流浹背孤个。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留沛简,地道東北人齐鲤。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像椒楣,于是被迫代替她去往敵國和親给郊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355