本篇請與上一篇一起服用。
頁面按鈕在啟用前,在右上角呈現黑白的狀態,在開發者設計的情景下才會啟用。對使用者來說,這樣可以減少干擾。對開發者來說,可以減少不必要的錯誤。
一言以蔽之,你的按鈕如果不是在任何頁面都有作用,請使用頁面按鈕,否則請使用瀏覽器按鈕。
按鈕的啟用方式需要工程師自己實作及設定,以下介紹兩種啟用頁面按鈕的方式。
首先來看以下這段設定檔以及事件腳本
設定檔:
{  
    "manifest_version" : 2,  
    "name" : "鐵人賽-Page-Action1",  
    "description" : "啟用方法一:只有在主機是:www.google.com.tw的網域底下啟用此頁面按鈕",  
    "version" : "2.0",  
    "page_action" : {  
        "default_title" : "啟用方法一",  
        "default_icon" : "icon.png",  
        "default_popup": "popup.html"          
    },  
    "background" : {  
        "scripts" : ["event.js"],  
        "persistent" : false  
    },  
    "permissions" : ["tabs"]  
}
事件腳本
//指定比對的url:不允許片段表達式   
//例如: *://*.google.com.tw/* 作為查詢字串不被接受因為host是一個片段表達式  
var urlPattern = '*://www.google.com.tw/*';  
//利用 tabs.query api 查找畫面上的所有tab  
function queryTabsAndShowPageActions(queryObject) {  
    chrome.tabs.query(queryObject,  
        function(tabs) {  
            if (tabs && tabs.length > 0) {  
                for (var i = 0; i < tabs.length; i++) {  
                    //在加載完畢的tab上,使用chrome.pageAction.show 啟用按鈕  
                    if (tabs[i].status === "complete") chrome.pageAction.show(tabs[i].id);  
                }  
            }  
        }  
    );  
}  
//第一次的初始化  
chrome.runtime.onInstalled.addListener(function() {  
    queryTabsAndShowPageActions({  
        "active": false,  
        "currentWindow": true,  
        "url": urlPattern  
    });  
});  
//每次tab有變動,檢查現在這個current tab是否在指定的 url pattern底下  
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {  
    queryTabsAndShowPageActions({  
        "active": true,  
        "currentWindow": true,  
        "url": urlPattern  
    });  
});  
上面這段腳本描述了兩段處理邏輯:
其一:處理已開啟的Tabs,使用query api來繞遍所有的已開的網址,並在載入完畢的tab中啟用頁面按鈕
//第一次的初始化  
chrome.runtime.onInstalled.addListener(function() {  
    queryTabsAndShowPageActions({  
        "active": false,  
        "currentWindow": true,  
        "url": urlPattern  
    });  
});
其二:處理新開啟的Tabs,查詢是否為指定網域,並啟用tab中的頁面按鈕。
//每次tab有變動,檢查現在這個current tab是否在指定的 url pattern底下  
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {  
    queryTabsAndShowPageActions({  
        "active": true,  
        "currentWindow": true,  
        "url": urlPattern  
    });  
});
這樣就完成了一個,只有在*://www.google.com.tw/*底下會啟用的頁面按鈕。
完整範例在:Github
所以說其實也是可以偷吃步在所有tab開啟頁面按鈕,不過這樣作並沒有太大的意義。
除了使用url,應該也能籍由內容腳本來偵測有無特定的DOM物件,然後通知事件腳本處理。不過如果只是這樣有更方便的方式,讓我們繼續往下看方法二。
chrome.tabs.query允許使用者用物件作為第一個參數查詢使用者目前開啟的所有書籤,在上面的程式碼中示範了在目前使用的視窗下,取得目前瀏覽的頁籤。回傳值會是一個tab物件,內含了網站url、title、等有用資訊。
使用tabs.query來查詢頁籤,可以使用Matches Patterns來過瀘取得的頁籤,但有一個很重要的限制,tabs.query不允許你使用片段表達式。
例如:
錯誤:會回傳不合規則的網址表達式
chrome.tabs.query({  
        "active": false,  
        "currentWindow": true,  
        "url":  `*://www.google.com.*/*`   
    },  
    function(tabs) {  
});
糾正結果:使用陣列指定多國家的google網域
chrome.tabs.query({  
        "active": false,  
        "currentWindow": true,  
        "url":  ['`*://www.google.com.tw/*','`*://www.google.com.hk/*'`]`  
    },  
    function(tabs) {  
});
接下來我們來討論另一種啟用頁面按鈕的方式,使用申明式內容(DeclarativeContent API)來啟用頁面按鈕。
以下截錄自chrome.declarativeContent API的非官方中文文件:https://crxdoc-zh.appspot.com/extensions/declarativeContent
使用chrome.declarativeContent API根據網頁內容進行某些操作,而不需要讀取網頁內容的權限。
聲明式內容API允許您根據網頁的URL和它的內容匹配的CSS選擇器來顯示您的擴展程序的頁面按鈕,而不需要擁有主機權限或插入內容腳本。為了在用戶單擊您的頁面按鈕後能夠與網頁交互,請使用activeTab權限。
如果您需要更精確地控制什麼時候顯示您的頁面按鈕,或者需要在用戶單擊它之前更改它的外觀以匹配當前標籤頁,您還是需要繼續使用頁面按鈕API。
設定檔
{  
    "manifest_version" : 2,  
    "name" : "鐵人賽-Page-Action2",  
    "description" : "啟用方法二:只有在主機是:www.google.com.tw 的網域底下啟用此頁面按鈕",  
    "version" : "2.0",  
    "page_action" : {  
        "default_title" : "啟用方法二",  
        "default_icon" : "icon.png",  
        "default_popup": "popup.html"          
    },  
    "background" : {  
        "scripts" : ["event.js"],  
        "persistent" : false  
    },  
    //記得宣告declarativeContent權限  
    "permissions" : ["tabs","declarativeContent"]  
}
以下程試碼展示了,當https://www.google.com/上的頁面存在密碼字段時,為該頁面啟用頁面按鈕。注意:所有條件(conditions)跟動作(actions)都使用new建構式。
//事件腳本  
var rule = {  
    //條件  
    conditions: [  
        new chrome.declarativeContent.PageStateMatcher({  
            //url的匹配指定  
            pageUrl: { hostContains: 'www.google.com.tw' },  
            //必需擁有此dom物件, 以css選擇器的行形式宣告  
            css: ["img"]  
        })  
    ],  
    //動作:啟用頁面按鈕  
    actions: [new chrome.declarativeContent.ShowPageAction()]  
};
規則的條件可以多個,以下為例:
  var rule = {  
    conditions: [  
      new chrome.declarativeContent.PageStateMatcher({  
        pageUrl: { hostContains: 'www.google.com'},  
        css: ["img"]  
      }),  
      new chrome.declarativeContent.PageStateMatcher({  
        css: ["video"]  
      })  
    ],  
    actions: [ new chrome.declarativeContent.ShowPageAction() ]  
  };
然後最重要的一點,記得在瀏覽器重啟時,去註消或是重新註冊規則:
//刪除規則,並重新註冊  
chrome.runtime.onInstalled.addListener(function(details) {  
    //移除所有舊規則  
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {  
        //註冊新規則  
        chrome.declarativeContent.onPageChanged.addRules([rule]);  
    });  
});
img tag的畫面,按鈕才會啟用。例如:https://www.google.com.tw/#q=haha
完整範例在:Github
資源: