[Chrome extension] 開始寫一個 Chrome extension 擴充功能

[Chrome extension] 開始寫一個 Chrome extension 擴充功能

今天這篇文章是在記錄如何寫一個簡單的 Chrome extension (擴充功能)~

為什麼要寫 extension 呢?因為 extension 可以幫你把許多事情變得更簡單~

像我這次寫的這個 extension 要解決的是 Great Suspender 的一個問題…

 

Great Suspender 是一個不錯用的 Chrome extension,

可以將長時間不用的 tab 先暫時凍結起來,節省一點系統資源~

不過,像我開很多 tab  的時候,可能就會有很多 tab 會進到凍結的狀態,

有時會想要讓他們全部重新整理,回到未凍結的狀態~

可是,單只是重新整理頁面是不行的,必須按下頁面上面的黃色區域才行:

Screen Shot 2014-09-21 at 下午1.40.04  

 

原本想裝一些可以重新整理所有頁面的 Chrome extension,來幫我把所有凍結的頁面都回復正常,

但因為單單重新整理沒有用,所以這些 extension 都無用武之地 (殘念)…

不過從 URL 的部分看來,原始的頁面 URL 是含在凍結頁的 URL 裡面,

舉例來說,chrome-extension://klbibkeccnjlkjkiokjodocebajanakg/suspended.html#url=http%3A%2F%2Flinux.die.net%2Fman%2F1%2Fatop

這個被凍結的頁面原始的 URL 就是 #url 後面的部分囉~

觀察一下,那個 URL 的部分應該是被 JavaScript 的 encodeURIComponent() 編碼過的…

只要能取得 URL,作一次 decodeURIComponent() 就能還原原始的 URL~

既然沒有 Chrome extension 可以作到這件事,就自己來寫一個吧,

順便記錄一下該怎麼寫一個新的 Chrome extension~

 

1. 參考相關文件 

要寫一個新的 Chrome extension,首先要造訪的自然是 Google 的官方網頁~

Getting Started: Building a Chrome Extension

花點時間好好看一下吧,而且 Chrome 也會更新裡面的一些東西,

像之前 Google 就修改了 manifest v2 的東西,也有可能增加新的 API~ 

 

2. 準備 manifest.json

這是一個 JSON 格式的檔案,用來告訴 Chrome 這個 extension 的一些相關資訊,

如名稱、敘述、版本、需要的權限、圖示、預設頁面等等~

這個 manifest 檔案要放在一個目錄裡面,

之後所有跟這 extension 相關的檔案也都要放在目錄裡面~

 

像我將這個 extension 的名稱取為 Reload Tabs,版本設定為 1.0,

使用 browser_action 表示會有一個圖示出現在 Chrome 的 extension 列上讓使用者點擊,

(因為我想要在點下圖示時,將所有的 Chrome tab 重新整理)

這裡面設定的圖示檔 (default_icon) 和點示圖示時要顯示的頁面 (default_popup) 都只是先取一個檔名,

還沒有實際的檔案~

{
"manifest_version": 2,
"name": "Reload Tabs",
"description": "Reload all Chrome tabs, including the ones that are frozen by Great Suspender",
"version": "1.0",
"permissions": [],
"browser_action":
{
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}

 

要注意的是目前的 manifest_version 必須設成 2 喔~

當然之後 Chrome 如果有再更新的話,有可能這裡會要求更新的 manifest 版本…

Chrome 會根據 manifest 的版本,來決定 extension 的一些行為與規範,

像是之前從 v1 改版至 v2 時,就要求加強一堆與安全性相關的功能

Chrome 會允許舊版的 manifest 使用一段時間,但寬限期過了之後,

如果 manifest 版本還是沒有更新到 Google 要求的話,

這個 Chrome extension 就無法再使用了,真是夠狠的~~

(我們的產品好像都沒辦法這樣搞,很古老的產品也得支援,

微軟已經停止支援的 Windows XP 我們還不知道要支援到天荒地老什麼時候~)

 

3. 準備 icon.png 圖示檔

基本上圖示檔是一個 19×19 的 PNG 檔案,

可以自己想辦法做一個出來,抓一個也可以 (要注意版權)~

網路上有很多免費的圖示可以抓,像我就從 IconFinder 找了個免費圖示下來用~

基本上也不需要去把圖縮成 19×19,Chrome 在顯示時自己就會縮圖了~

icon  

 

4. 測試一下新寫的 extension (圖示)

當然 extension 的部分都還沒寫到什麼,不過可以先看看圖示的效果~

在 Chrome extension 列上隨便一個圖示上按右鍵 > Manage,

或是在網址列上打 chrome://extensions/ 進到 extension 的管理頁面~

把右上角的 Developer mode 打勾,

可以看到下面出現了幾個開發 extension 用的按鈕~

Screen Shot 2014-09-21 at 下午11.52.47  

 

選擇 Load unpacked extension… 按鈕後,選取包含 extension 檔案的那個目錄,

Chrome 就會將我們新寫的 extension 讀進來了~感動~~ ^^

Screen Shot 2014-09-21 at 下午11.55.11  

 

而且在 extension 圖示列上,也出現了我們的圖示囉:

Screen Shot 2014-09-21 at 下午11.58.28  

 

試著點一下圖示,出現了網頁找不到的錯誤,不過這也是預期中的~

Screen Shot 2014-09-22 at 上午12.08.45  

 

5. 準備 popup.html 網頁檔 (初版)

這個 html 檔案是按下圖示時,會顯示的網頁,

因此我們要做的事可以寫在裡面~

當然 Chrome extension 還有其他觸發的方式 (像是背景頁面 background pages),

不過以我們這個 extension 的需求來說,相當足夠了:

點下圖示 -> 顯示一個網頁,裡面用 javascript 把所有的 tab 都重新整理,

順便顯示一個訊息說目前正在重新整理 -> 完成!

 

那就先來建立一個最簡單的網頁檔 popup.html 吧~

雖然我還不會 HTML5,不過這是個趨勢,趁這時間學一點皮毛也是好的~

w3schools: HTML5 Introduction 複製一個 HTML5 的樣版網頁下來,稍微修改一下: 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Reload Tabs</title>
</head>
<body>
Hello! This is Reload Tabs extension!
</body>
</html>

 

這個網頁的內容就是顯示一段 Hello 字串,

改好之後,點下 extension 圖示就可以立刻看到效果~

(沒有的話,到 chrome://extensions/ 頁面對 extension 選擇 Reload):

Screen Shot 2014-09-23 at 上午12.12.52  

 

可以看到,Chrome 會將網頁內容顯示在一個像對話框的東西裡面,

不過這對話框的寬度似乎有點小?

其實是因為我們並沒有指定網頁的 style width,

有指定的話,這個對話框也會相應的變大囉~

 

6. 在 popup.html 中加入 Javascript 來重新整理所有的 tab

接下來,我們要在 popup.html 裡加入一些 Javascript,

好來重新整理所有的 tab 囉~

要如何取得 Chrome 中所有的 tab 呢?

如果有仔細看 Chrome extension 的文件的話,應該會注意到 chrome.tabs 這一頁~

這裡面提到了 chrome.tabs.query() 這個 API 可以用來查詢 Chrome 的 tab~

直覺的在 popup.html 中加上 Javascript 碼來試試看:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Reload Tabs</title>
<script>
alert("script");
chrome.tabs.query({}, function(tabs) {
alert(tabs);
});
</script>
</head>
<body>
Hello! This is Reload Tabs extension!
</body>
</html>

 

怪了,點下圖示後還是只顯示了 Hello 訊息,沒有預期的 alert 對話框?!

就算在 chrome://extensions/ 頁面對 extension 選擇 Reload 也是一樣…

瞄一下 Chrome Tutorial: Debugging 這邊的說明吧~

在 extension 圖示上按右鍵 > Inspect Popup 就可以跳出 Chrome developer tools 視窗來幫助除錯:

Screen Shot 2014-09-23 at 上午12.59.35  

 

從下面的錯誤訊息中,可以發現是違反了 script-src 這個 Content Security Policy…

Screen Shot 2014-09-23 at 上午1.00.17  

 

這個 Content Security Policy 是什麼東東呢?

基本上就是一些跟 Chrome extension 安全性相關的規則,

Google 為了避免 Chrome extension 本身造成危害,因此設定了一些規矩,

可以參考 Chrome Content Security Policy (CSP) 這個頁面~

舉例來說,下面這些是被禁止的:

1. Eval and related functions are disabled

2. Inline JavaScript will not be executed

3. Only local script and resources are loaded

 

看來我們在 popup.html 中直接寫 inline 的 <script> 是撞到 CSP 的原因…

既然不能用 inline script,只好把它移到另一個外部的 JavaScript 檔案去囉~

 

7. 準備一個 popup.js 來執行 JavaScript

把原本在 popup.html 中的 <script></script> 的內容移到新的 popup.js 檔案中: 

alert("script");
chrome.tabs.query({}, function(tabs) {
alert(tabs);
});

 

原本的 popup.html 中的 <script> 就改成連結至這個 popup.js:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Reload Tabs</title>
<script src="popup.js"></script>
</head>
<body>
Hello! This is Reload Tabs extension!
</body>
</html>

 

重新點一下圖示,這次就有正常的出現 alert 視窗,表示我們寫的 JavaScript 有作用了!

Screen Shot 2014-09-24 at 上午12.05.14  

 

8. 修改 popup.js 使其可以謮取 tabs 的資訊

接下來就是把 popup.js 這個 JavaScript 修改一下,讓它可以讀到所有的 tab…

這邊用 console.log() 把訊息寫到 debug console 上去,

因此要在 extension 圖示上按右鍵 > Inspect Popup 的方式看訊息:

chrome.tabs.query({}, function(tabs) {
for (var i = 0; i < tabs.length; i++)
{
console.log(tabs[i]);
}
});

 

點開其中一個 Tab object 來看:

Screen Shot 2014-09-24 at 上午12.18.55  

 

嗯… 看來資訊跟 chrome.tabs 這邊的 property 的說明部分差不多,不過少了 url…

在 url 的地方,網頁上特別提及如果要使用 tab 的 url 屬性的話,

要在 manifest.json 中加入 “tabs” 的 permission:

於是 manifest.json 會變成這樣:

{
"manifest_version": 2,
"name": "Reload Tabs",
"description": "Reload all Chrome tabs, including the ones that are frozen by Great Suspender",
"version": "1.0",
    "permissions":
[
"tabs"
],
"browser_action":
{
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}

 

到 extension 管理頁面將 extension 重新載入後,再點 Inspect popup,

這次就可以成功拿到 tab 的 url 了:

Screen Shot 2014-09-24 at 上午12.27.35  

 

9. 修改 popup.js 使其可以重新整理所有的 tabs

既然已經可以讀到所有 tab 的 url,要重新整理也就很簡單了,只要呼叫 chrome.tabs.reload() 就行~

(不過後來測試結果,chrome.tabs.reload() 會連表單的部分也重送,

跟我只想要單純重新整理 URL 不同,因此後來就不採用 reload() 了)

 

不過我們還想連 Great Suspender 凍結的 tab 也重新整理,

那就必須將 url 讀出來之後,取出 #url 後面的部分作 URL decoding,用這當作那 tab 的新 url~

於是修改後的 popup.js 變成這樣:

chrome.tabs.query({}, function(tabs)
{
const URL_PATTERN = "/suspended.html#url=";
for (var i = 0; i < tabs.length; i++)
{
var nTabID  = tabs[i].id;
var sTabURL = tabs[i].url;
if (sTabURL != null)
{
// Check if this tab is frozen by Great Suspender
var nPos = sTabURL.indexOf(URL_PATTERN);
if (nPos >= 0)
{
// This tab is suspended by Great Suspender.
//  Reload with original url.
sTabURL = decodeURIComponent(sTabURL.substr(nPos+URL_PATTERN.length));
}
// Reload the tab
chrome.tabs.update(nTabID, {"url": sTabURL});
}
}
});

 

測試一下新寫好的 extension 吧~

按下圖示後,所有的 tab 都被重新整理了,被 Great Suspender 凍結的頁面也都回復正常~

整個 extension 的任務可算是圓滿成功 🙂

Screen Shot 2014-09-24 at 上午1.08.58  

 

不過到目前為止,都還只是個 Developer 版本的 chrome extension…

之後再來寫一篇將 chrome extension 上架到 Chrome App Store 的文章吧~~^^

 

(本頁面已被瀏覽過 3,620 次)

One thought on “[Chrome extension] 開始寫一個 Chrome extension 擴充功能

  1. 謝謝提供非常實用的教學!
    版主回覆:(11/17/2014 03:51:25 PM)
    不客氣,希望有幫上忙~:)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料